All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yoshinori Sato <ysato@users.sourceforge.jp>
To: linux-sh@vger.kernel.org
Cc: "Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Damien Le Moal" <dlemoal@kernel.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>,
	"Conor Dooley" <conor+dt@kernel.org>,
	"Geert Uytterhoeven" <geert+renesas@glider.be>,
	"Michael Turquette" <mturquette@baylibre.com>,
	"Stephen Boyd" <sboyd@kernel.org>,
	"Maarten Lankhorst" <maarten.lankhorst@linux.intel.com>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Thomas Zimmermann" <tzimmermann@suse.de>,
	"David Airlie" <airlied@gmail.com>,
	"Daniel Vetter" <daniel@ffwll.ch>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Krzysztof Wilczyński" <kw@linux.com>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Jiri Slaby" <jirislaby@kernel.org>,
	"Magnus Damm" <magnus.damm@gmail.com>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Rich Felker" <dalias@libc.org>,
	"John Paul Adrian Glaubitz" <glaubitz@physik.fu-berlin.de>,
	"Lee Jones" <lee@kernel.org>, "Helge Deller" <deller@gmx.de>,
	"Heiko Stuebner" <heiko@sntech.de>,
	"Jernej Skrabec" <jernej.skrabec@gmail.com>,
	"Chris Morgan" <macromorgan@hotmail.com>,
	"Yang Xiwen" <forbidden405@foxmail.com>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Linus Walleij" <linus.walleij@linaro.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Vlastimil Babka" <vbabka@suse.cz>,
	"Hyeonggon Yoo" <42.hyeyoo@gmail.com>,
	"David Rientjes" <rientjes@google.com>,
	"Baoquan He" <bhe@redhat.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Guenter Roeck" <linux@roeck-us.net>,
	"Stephen Rothwell" <sfr@canb.auug.org.au>,
	"Azeem Shaikh" <azeemshaikh38@gmail.com>,
	"Javier Martinez Canillas" <javierm@redhat.com>,
	"Max Filippov" <jcmvbkbc@gmail.com>,
	"Palmer Dabbelt" <palmer@rivosinc.com>,
	"Bin Meng" <bmeng@tinylab.org>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Jacky Huang" <ychuang3@nuvoton.com>,
	"Lukas Bulwahn" <lukas.bulwahn@gmail.com>,
	"Biju Das" <biju.das.jz@bp.renesas.com>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Sam Ravnborg" <sam@ravnborg.org>,
	"Sergey Shtylyov" <s.shtylyov@omp.ru>,
	"Michael Karcher" <kernel@mkarcher.dialup.fu-berlin.de>,
	"Laurent Pinchart" <laurent.pinchart+renesas@ideasonboard.com>,
	linux-ide@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, dri-devel@lists.freedesktop.org,
	linux-pci@vger.kernel.org, linux-serial@vger.kernel.org,
	linux-fbdev@vger.kernel.org
Subject: [DO NOT MERGE v6 23/37] mfd: sm501: Convert platform_data to OF property
Date: Tue,  9 Jan 2024 17:23:20 +0900	[thread overview]
Message-ID: <569f0bfb4fa3fcec8fbd64f67fc4fd2d1cba3f77.1704788539.git.ysato@users.sourceforge.jp> (raw)
In-Reply-To: <cover.1704788539.git.ysato@users.sourceforge.jp>

Various parameters of SM501 can be set using platform_data,
so parameters cannot be passed in the DeviceTree target.
Expands the parameters set in platform_data so that they can be
specified using DeviceTree properties.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 drivers/mfd/sm501.c           | 436 ++++++++++++++++++++++++++++++++++
 drivers/video/fbdev/sm501fb.c | 106 +++++++++
 2 files changed, 542 insertions(+)

diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 28027982cf69..3408778e0048 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -82,6 +82,23 @@ struct sm501_devdata {
 	unsigned int			 rev;
 };
 
+enum prop_type {
+	PROP_NUM, PROP_STR,
+};
+
+enum val_type {
+	ENDIS, MT_EX, MT_XC, MT_SSM, MT_SM, MT_DEBUG, MT_DIV, MT_USB, MT_DELAY,
+	MC_PAD,	MC_USBCLK, MC_SSP, MC_FP, MC_FREQ, MC_REFRESH, MC_HOLD, MC_SH,
+	MC_II, MC_GAP, MC_DAC, MC_MC, MC_BL, MC_USB, MC_LB, MC_VR,
+};
+
+struct sm501_config_props {
+	char *name;
+	u32 shift;
+	u32 width;
+	enum prop_type prop_type;
+	enum val_type val_type;
+};
 
 #define MHZ (1000 * 1000)
 
@@ -1370,6 +1387,419 @@ static int sm501_init_dev(struct sm501_devdata *sm)
 	return 0;
 }
 
+static u32 lookup_str(const char *val, const char * const *list)
+{
+	u32 ret = 0;
+
+	while (*list) {
+		if (strcmp(val, *list) == 0)
+			return ret;
+		list++;
+		ret++;
+	}
+	return ~0;
+}
+
+static u32 lookup_num(u32 val, const u32 *list)
+{
+	u32 ret = 0;
+
+	while (*list != ~0) {
+		if (val == *list)
+			return ret;
+		list++;
+		ret++;
+	}
+	return ~0;
+}
+
+static const struct sm501_config_props misc_timming[] = {
+	{"ex",      28, 4, PROP_NUM, MT_EX},
+	{"xc",      24, 2, PROP_STR, MT_XC},
+	{"us",      23, 1, PROP_STR, ENDIS},
+	{"ssm1",    20, 1, PROP_STR, MT_SSM},
+	{"sm1",     16, 4, PROP_NUM, MT_SM},
+	{"ssm0",    12, 1, PROP_STR, MT_SSM},
+	{"sm0",      8, 4, PROP_NUM, MT_SM},
+	{"deb",      7, 1, PROP_STR, MT_DEBUG},
+	{"acpi",     6, 1, PROP_STR, ENDIS},
+	{"divider",  4, 2, PROP_NUM, MT_DIV},
+	{"usb-mode", 3, 1, PROP_STR, MT_USB},
+	{"delay",    0, 3, PROP_NUM, MT_DELAY},
+	{},
+};
+
+static const struct sm501_config_props misc_control[] = {
+	{"pad",      30, 2, PROP_NUM, MC_PAD},
+	{"usbclk",   28, 2, PROP_STR, MC_USBCLK},
+	{"uart-ssp", 27, 1, PROP_STR, MC_SSP},
+	{"lat",      26, 1, PROP_STR, ENDIS},
+	{"fp",       25, 1, PROP_NUM, MC_FP},
+	{"freq",     24, 1, PROP_NUM, MC_FREQ},
+	{"refresh",  21, 2, PROP_NUM, MC_REFRESH},
+	{"hold",     18, 3, PROP_NUM, MC_HOLD},
+	{"sh",       17, 1, PROP_STR, MC_SH},
+	{"ii",       16, 1, PROP_STR, MC_II},
+	{"pll",      15, 1, PROP_STR, ENDIS},
+	{"gap",      13, 2, PROP_STR, MC_GAP},
+	{"dac",      12, 1, PROP_STR, MC_DAC},
+	{"mc",       11, 1, PROP_STR, MC_MC},
+	{"bl",       10, 1, PROP_NUM, MC_BL},
+	{"usb",       9, 1, PROP_STR, MC_USB},
+	{"lb",        8, 1, PROP_STR, MC_LB},
+	{"vr",        4, 1, PROP_NUM, MC_VR},
+	{},
+};
+
+/* Read configuration values */
+static void sm501_of_read_config(struct device *dev, struct device_node *np,
+				 const char *prefix,
+				 const struct sm501_config_props *props,
+				 struct sm501_reg_init *ret)
+{
+	static const char * const endis[] = { "disable", "enable", NULL };
+	static const char * const xc[] = { "internal-pll", "hclk", "gpio33", NULL };
+	static const char * const ssm[] = { "288mhz", "div", NULL };
+	static const char * const debmode[] = { "input-reference", "output", NULL };
+	static const char * const usbmode[] = { "normal", "simulation", NULL };
+	static const char * const usbclk[] = { "crystal", "-", "96mhz", "48mhz", NULL };
+	static const char * const ssp[] = { "uart1", "ssp1", NULL };
+	static const char * const sh_ready[] = { "active-low", "active-high", NULL };
+	static const char * const int_invert[] = { "normal", "invert", NULL };
+	static const char * const slave[] = { "cpu", "8051", NULL };
+	static const char * const usbport[] = { "master", "slave", NULL };
+	static const char * const usbloop[] = { "normal", "loopback", NULL };
+
+	static const u32 divrate[] = { 336, 288, 240, 192, ~0 };
+	static const u32 fpdata[] = { 18, 24, ~0 };
+	static const u32 cfreq[] = { 24, 12, ~0 };
+	static const u32 bushold[] = { 0, 8, 16, 24, 32, ~0 };
+	static const u32 burst[] = { 8, 1, ~0 };
+	static const u32 vrmem[] = { 30, 62, ~0 };
+
+	struct device_node *child;
+	const char *sval;
+	u32 mask;
+	u32 val;
+	int err;
+
+	ret->mask = ~0;
+	ret->set = 0;
+
+	child = of_get_child_by_name(np, prefix);
+	if (!child)
+		return;
+
+	while (props->name) {
+		switch (props->prop_type) {
+		case PROP_NUM:
+			err = of_property_read_u32(child, props->name, &val);
+			break;
+		case PROP_STR:
+			err = of_property_read_string(child, props->name, &sval);
+			break;
+		}
+		if (!err) {
+			switch (props->val_type) {
+			case ENDIS:
+				val = lookup_str(sval, endis);
+				break;
+			case MT_EX:
+				val /= 16;
+				break;
+			case MT_XC:
+				val = lookup_str(sval, xc);
+				break;
+			case MT_SSM:
+				val = lookup_str(sval, ssm);
+				break;
+			case MT_SM:
+				if ((val % 3) == 0) {
+					val /= 3;
+					val = ffs(val);
+					val += 8;
+				} else {
+					val = ffs(val);
+				}
+				break;
+			case MT_DEBUG:
+				val = lookup_str(sval, debmode);
+				break;
+			case MT_DIV:
+				val = lookup_num(val, divrate);
+				break;
+			case MT_USB:
+				val = lookup_str(sval, usbmode);
+				break;
+			case MT_DELAY:
+				val /= 5;
+				break;
+			case MC_PAD:
+				val /= 8;
+				val = 2 - val;
+				break;
+			case MC_USBCLK:
+				val = lookup_str(sval, usbclk);
+				break;
+			case MC_SSP:
+				val = lookup_str(sval, ssp);
+				break;
+			case MC_FP:
+				val = lookup_num(val, fpdata);
+				break;
+			case MC_FREQ:
+				val = lookup_num(val, cfreq);
+				break;
+			case MC_REFRESH:
+				val = ffs(val) - 3;
+				break;
+			case MC_HOLD:
+				val = lookup_num(val, bushold);
+				break;
+			case MC_SH:
+				val = lookup_str(sval, sh_ready);
+				break;
+			case MC_II:
+				val = lookup_str(sval, int_invert);
+				break;
+			case MC_GAP:
+				if (!strcmp(sval, "default"))
+					val = 0;
+				else
+					val = ~0;
+				break;
+			case MC_DAC:
+				val = lookup_str(sval, endis) ^ 1;
+				break;
+			case MC_MC:
+				val = lookup_str(sval, slave);
+				break;
+			case MC_BL:
+				val = lookup_num(val, burst);
+				break;
+			case MC_USB:
+				val = lookup_str(sval, usbport);
+				break;
+			case MC_LB:
+				val = lookup_str(sval, usbloop);
+				break;
+			case MC_VR:
+				val = lookup_num(val, vrmem);
+				break;
+			}
+			mask = (1 << props->width) - 1;
+			if (mask >= val) {
+				mask = ~(mask << props->shift);
+				ret->mask &= mask;
+				ret->set |= val << props->shift;
+			} else {
+				switch (props->prop_type) {
+				case PROP_NUM:
+					dev_warn(dev, "%s invalid value %d",
+						 props->name, val);
+
+					break;
+				case PROP_STR:
+					dev_warn(dev, "%s invalid value %s",
+						 props->name, sval);
+					break;
+				}
+			}
+		}
+		props++;
+	}
+}
+
+/* Read GPIO control */
+/*
+ * DT example.
+ * gpio-pin-control {
+ *   pin@0 {
+ *	 gpio-port;
+ *   };
+ *   pin@1 {
+ *	 function;
+ *   };
+ * };
+ */
+static void sm501_of_read_gpio(struct device *dev, struct device_node *np,
+			       struct sm501_reg_init *hi, struct sm501_reg_init *low)
+{
+	struct device_node *gpio_group, *pin;
+	const char *prop_mode;
+	unsigned int pin_no;
+	int mode;
+	u64 mask;
+	u64 set;
+
+	mask = ~0;
+	set = 0;
+	gpio_group = of_get_child_by_name(np, "gpio-pin-control");
+	if (gpio_group) {
+		for_each_child_of_node(gpio_group, pin) {
+			mode = -1;
+			if (sscanf(pin->full_name, "pin@%u", &pin_no) == 1) {
+				if (of_property_read_bool(pin, "gpio-port"))
+					mode = 0;
+				else if (of_property_read_bool(pin, "function"))
+					mode = 1;
+			}
+			/* GPIO0 - 47 and 55 -63 */
+			if (mode < 0 ||
+			    (pin_no >= 64 || (pin_no >= 48 && pin_no <= 54))) {
+				dev_warn(dev,
+					 "%s mode %s is invalid.", pin->name, prop_mode);
+			} else {
+				mask &= ~(1 << pin_no);
+				set |= mode << pin_no;
+			}
+		}
+	}
+	hi->set = set >> 32;
+	low->set = set & 0xffffffff;
+	hi->mask = mask >> 32;
+	low->mask = mask & 0xffffffff;
+}
+
+static inline int read_i2c_prop(struct device *dev, struct device_node *child,
+				const char *name, u32 *val)
+{
+	if (of_property_read_u32(child, name, val)) {
+		dev_warn(dev, "%s/%s not found. skip it.", of_node_full_name(child), name);
+		return -ENOENT;
+	}
+	return 0;
+}
+
+/* Read GPIO I2C configuration */
+/*
+ * DT example.
+ * gpio-i2c {
+ *    i2c@0 {
+ *	sda = <gpio-pin>;
+ *	scl = <gpio-pin>;
+ *	delay = <delay>;
+ *	timeout = <timeout>;
+ *    };
+ *    i2c@1 {
+ *      :
+ *    };
+ *    :
+ * };
+ */
+static int sm501_parse_dt_gpio_i2c(struct device *dev, struct sm501_platdata *plat,
+				   struct device_node *np)
+{
+	struct device_node *i2c_group, *child;
+	unsigned int i;
+	u32 i2c_nr;
+	int err;
+
+	i2c_group = of_get_child_by_name(np, "gpio-i2c");
+	if (!i2c_group)
+		return 0;
+
+	i2c_nr = of_get_child_count(i2c_group);
+	plat->gpio_i2c = devm_kzalloc(dev, sizeof(*plat->gpio_i2c) * i2c_nr,
+				      GFP_KERNEL);
+	if (!plat->gpio_i2c)
+		return -ENOMEM;
+
+	plat->gpio_i2c_nr = i2c_nr;
+	i = 0;
+	for_each_child_of_node(i2c_group, child) {
+		u32 bus;
+
+		if (sscanf(child->full_name, "i2c@%u", &bus) != 1) {
+			dev_warn(dev, "Unknown address %s\n", child->name);
+			continue;
+		}
+
+		err = 0;
+		plat->gpio_i2c[i].bus_num = bus;
+		err += read_i2c_prop(dev, child, "sda", &plat->gpio_i2c[i].pin_sda);
+		err += read_i2c_prop(dev, child, "scl", &plat->gpio_i2c[i].pin_scl);
+		err += read_i2c_prop(dev, child, "delay", &plat->gpio_i2c[i].udelay);
+		err += read_i2c_prop(dev, child, "timeout", &plat->gpio_i2c[i].timeout);
+		if (err == 0)
+			i++;
+	}
+
+	return 0;
+}
+
+/* Read device functions */
+static u32 sm501_read_devices(struct device *dev, struct device_node *np)
+{
+	static const char * const funcname[] = {
+		"usb-host", "usb-slave", "ssp0", "ssp1",
+		"uart0", "uart1", "fbaccel", "ac97",
+		"i2s", "gpio",
+	};
+	struct property *prop;
+	unsigned int i;
+	const char *s;
+	u32 ret = 0;
+
+	of_property_for_each_string(np, "smi,devices", prop, s) {
+		for (i = 0; i < ARRAY_SIZE(funcname); i++) {
+			if (strcmp(s, funcname[i]) == 0) {
+				ret |= 1 << i;
+				goto next;
+			}
+		}
+		dev_warn(dev, "Unknown device function '%s'", s);
+next:
+	}
+	if (!ret)
+		dev_warn(dev, "devices not defined. disable all functions.");
+	return ret;
+}
+
+/* Build platform_data from OF property */
+struct plat_dt {
+	struct sm501_platdata plat;
+	struct sm501_initdata init;
+};
+
+static int sm501_parse_dt(struct sm501_devdata *sm, struct device_node *np)
+{
+	struct sm501_platdata *plat;
+	struct plat_dt *dt_p;
+	u32 word;
+	int ret;
+
+	dt_p = devm_kzalloc(sm->dev, sizeof(*dt_p), GFP_KERNEL);
+	if (!dt_p)
+		return -ENOMEM;
+
+	plat = &dt_p->plat;
+	plat->init = &dt_p->init;
+
+	plat->init->devices = sm501_read_devices(sm->dev, np);
+	/* mclk and m1xclk are not u32, so convert between them using intermediate variables. */
+	of_property_read_u32(np, "smi,mclk", &word);
+	plat->init->mclk = word;
+	of_property_read_u32(np, "smi,m1xclk", &word);
+	plat->init->m1xclk = word;
+
+	sm501_of_read_config(sm->dev, np, "misc-timing", misc_timming,
+			     &plat->init->misc_timing);
+	sm501_of_read_config(sm->dev, np, "misc-control", misc_control,
+			     &plat->init->misc_control);
+	sm501_of_read_gpio(sm->dev, np,
+			   &plat->init->gpio_high, &plat->init->gpio_low);
+
+	if (IS_ENABLED(CONFIG_MFD_SM501_GPIO) &&
+	    (plat->init->devices & SM501_USE_GPIO)) {
+		ret = sm501_parse_dt_gpio_i2c(sm->dev, plat, np);
+		if (ret)
+			return ret;
+	}
+	sm->platdata = plat;
+	return 0;
+}
+
 static int sm501_plat_probe(struct platform_device *dev)
 {
 	struct sm501_devdata *sm;
@@ -1406,6 +1836,12 @@ static int sm501_plat_probe(struct platform_device *dev)
 		goto err_res;
 	}
 
+	if (IS_ENABLED(CONFIG_OF) && dev->dev.of_node) {
+		ret = sm501_parse_dt(sm, dev->dev.of_node);
+		if (ret)
+			goto err_res;
+	}
+
 	platform_set_drvdata(dev, sm);
 
 	sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c
index d6fdc1737cd2..5de00f2570aa 100644
--- a/drivers/video/fbdev/sm501fb.c
+++ b/drivers/video/fbdev/sm501fb.c
@@ -1932,6 +1932,106 @@ static int sm501fb_start_one(struct sm501fb_info *info,
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static u32 read_display_flags(struct device_node *np)
+{
+	static const char * const name[] = {
+		"use-init-done", "disable-at-exit", "use-hwcursor", "use-hwaccel",
+		"panel-no-fpen", "panel-no-vbiasen", "panel-inv-fpen", "panel-inv-vbiasen",
+	};
+
+	struct property *prop;
+	unsigned int i;
+	const char *s;
+	u32 ret = 0;
+
+	of_property_for_each_string(np, "smi,flags", prop, s) {
+		for (i = 0; i < ARRAY_SIZE(name); i++) {
+			if (strcmp(s, name[i]) == 0) {
+				ret |= 1 << i;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+/* parse CRT / panel configuration */
+static struct sm501_platdata_fbsub *dt_fbsub(struct device *dev,
+					     struct device_node *np,
+					     const char *name)
+{
+	struct sm501_platdata_fbsub *fbsub = NULL;
+	struct fb_videomode *def_mode = NULL;
+	struct device_node *child;
+	const void *p_edid;
+	u32 flags = 0;
+	u32 bpp = 0;
+	int len;
+
+	child = of_get_child_by_name(np, name);
+	if (child == NULL)
+		return NULL;
+
+	p_edid = of_get_property(child, "edid", &len);
+	if (p_edid && len == EDID_LENGTH) {
+		struct fb_monspecs *specs;
+		u8 *edid;
+
+		edid = kmemdup(p_edid, EDID_LENGTH, GFP_KERNEL);
+		if (edid) {
+			specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+			if (specs) {
+				fb_edid_to_monspecs(edid, specs);
+				def_mode = specs->modedb;
+			}
+		}
+		kfree(edid);
+	}
+
+	of_property_read_u32(child, "bpp", &bpp);
+
+	/* If flags property is obtained, fbsub is returned. */
+	flags = read_display_flags(child);
+	if (flags) {
+		fbsub = devm_kzalloc(dev, sizeof(*fbsub), GFP_KERNEL);
+		if (fbsub) {
+			fbsub->def_mode = def_mode;
+			fbsub->def_bpp = bpp;
+			fbsub->flags = flags;
+		}
+	}
+	return fbsub;
+}
+
+/* Build platform_data from OF property */
+static struct sm501_platdata_fb *pdata_from_dt(struct device *dev, struct device_node *np)
+{
+	enum sm501_fb_routing fb_route = SM501_FB_OWN;
+	struct sm501_platdata_fb *pdata = NULL;
+	struct sm501_platdata_fbsub *fb_crt;
+	struct sm501_platdata_fbsub *fb_pnl;
+	unsigned int flags = 0;
+
+	if (of_property_read_bool(np, "route-crt-panel"))
+		fb_route = SM501_FB_CRT_PANEL;
+	if (of_property_read_bool(np, "swap-fb-endian"))
+		flags = SM501_FBPD_SWAP_FB_ENDIAN;
+	fb_crt = dt_fbsub(dev, np, "crt");
+	fb_pnl = dt_fbsub(dev, np, "panel");
+	if (fb_crt || fb_pnl) {
+		pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+		if (pdata) {
+			pdata->fb_route = fb_route;
+			pdata->flags = flags;
+			pdata->fb_crt = fb_crt;
+			pdata->fb_pnl = fb_pnl;
+		}
+	}
+	return pdata;
+}
+#endif
+
 static int sm501fb_probe(struct platform_device *pdev)
 {
 	struct sm501fb_info *info;
@@ -1974,6 +2074,12 @@ static int sm501fb_probe(struct platform_device *pdev)
 				if (info->edid_data)
 					found = 1;
 			}
+			/* Get platform data compatible configuration */
+			if (!found) {
+				info->pdata = pdata_from_dt(dev, np);
+				if (info->pdata)
+					found = 1;
+			}
 		}
 #endif
 		if (!found) {
-- 
2.39.2


WARNING: multiple messages have this Message-ID (diff)
From: Yoshinori Sato <ysato@users.sourceforge.jp>
To: linux-sh@vger.kernel.org
Cc: "Krzysztof Wilczyński" <kw@linux.com>,
	linux-fbdev@vger.kernel.org, "Rich Felker" <dalias@libc.org>,
	"Geert Uytterhoeven" <geert+renesas@glider.be>,
	"Bin Meng" <bmeng@tinylab.org>,
	"Michael Turquette" <mturquette@baylibre.com>,
	linux-pci@vger.kernel.org, "Jacky Huang" <ychuang3@nuvoton.com>,
	"Palmer Dabbelt" <palmer@rivosinc.com>,
	linux-kernel@vger.kernel.org, "Max Filippov" <jcmvbkbc@gmail.com>,
	"Lee Jones" <lee@kernel.org>,
	"Krzysztof Kozlowski" <krzysztof.kozlowski+dt@linaro.org>,
	"Hyeonggon Yoo" <42.hyeyoo@gmail.com>,
	"Jiri Slaby" <jirislaby@kernel.org>,
	linux-clk@vger.kernel.org,
	"Stephen Rothwell" <sfr@canb.auug.org.au>,
	"Laurent Pinchart" <laurent.pinchart+renesas@ideasonboard.com>,
	"Yoshinori Sato" <ysato@users.sourceforge.jp>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Helge Deller" <deller@gmx.de>,
	"Daniel Lezcano" <daniel.lezcano@linaro.org>,
	"Magnus Damm" <magnus.damm@gmail.com>,
	"Javier Martinez Canillas" <javierm@redhat.com>,
	"Jernej Skrabec" <jernej.skrabec@gmail.com>,
	linux-serial@vger.kernel.org,
	"David Rientjes" <rientjes@google.com>,
	"Lukas Bulwahn" <lukas.bulwahn@gmail.com>,
	"Lorenzo Pieralisi" <lpieralisi@kernel.org>,
	"Guenter Roeck" <linux@roeck-us.net>,
	devicetree@vger.kernel.org, "Conor Dooley" <conor+dt@kernel.org>,
	"Arnd Bergmann" <arnd@arndb.de>,
	"Uwe Kleine-König" <u.kleine-koenig@pengutronix.de>,
	"Maxime Ripard" <mripard@kernel.org>,
	"Sam Ravnborg" <sam@ravnborg.org>,
	"Rob Herring" <robh+dt@kernel.org>,
	dri-devel@lists.freedesktop.org,
	"Chris Morgan" <macromorgan@hotmail.com>,
	"John Paul Adrian Glaubitz" <glaubitz@physik.fu-berlin.de>,
	"Bjorn Helgaas" <bhelgaas@google.com>,
	"Thomas Gleixner" <tglx@linutronix.de>,
	"Vlastimil Babka" <vbabka@suse.cz>,
	"Yang Xiwen" <forbidden405@foxmail.com>,
	"Sergey Shtylyov" <s.shtylyov@omp.ru>,
	"Baoquan He" <bhe@redhat.com>,
	linux-ide@vger.kernel.org, "Stephen Boyd" <sboyd@kernel.org>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Randy Dunlap" <rdunlap@infradead.org>,
	"Biju Das" <biju.das.jz@bp.renesas.com>,
	"Sebastian Reichel" <sre@kernel.org>,
	"Azeem Shaikh" <azeemshaikh38@gmail.com>,
	linux-renesas-soc@vger.kernel.org,
	"Damien Le Moal" <dlemoal@kernel.org>,
	"Thomas Zimmermann" <tzimmermann@suse.de>,
	"Michael Karcher" <kernel@mkarcher.dialup.fu-berlin.de>,
	"Andrew Morton" <akpm@linux-foundation.org>
Subject: [DO NOT MERGE v6 23/37] mfd: sm501: Convert platform_data to OF property
Date: Tue,  9 Jan 2024 17:23:20 +0900	[thread overview]
Message-ID: <569f0bfb4fa3fcec8fbd64f67fc4fd2d1cba3f77.1704788539.git.ysato@users.sourceforge.jp> (raw)
In-Reply-To: <cover.1704788539.git.ysato@users.sourceforge.jp>

Various parameters of SM501 can be set using platform_data,
so parameters cannot be passed in the DeviceTree target.
Expands the parameters set in platform_data so that they can be
specified using DeviceTree properties.

Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp>
---
 drivers/mfd/sm501.c           | 436 ++++++++++++++++++++++++++++++++++
 drivers/video/fbdev/sm501fb.c | 106 +++++++++
 2 files changed, 542 insertions(+)

diff --git a/drivers/mfd/sm501.c b/drivers/mfd/sm501.c
index 28027982cf69..3408778e0048 100644
--- a/drivers/mfd/sm501.c
+++ b/drivers/mfd/sm501.c
@@ -82,6 +82,23 @@ struct sm501_devdata {
 	unsigned int			 rev;
 };
 
+enum prop_type {
+	PROP_NUM, PROP_STR,
+};
+
+enum val_type {
+	ENDIS, MT_EX, MT_XC, MT_SSM, MT_SM, MT_DEBUG, MT_DIV, MT_USB, MT_DELAY,
+	MC_PAD,	MC_USBCLK, MC_SSP, MC_FP, MC_FREQ, MC_REFRESH, MC_HOLD, MC_SH,
+	MC_II, MC_GAP, MC_DAC, MC_MC, MC_BL, MC_USB, MC_LB, MC_VR,
+};
+
+struct sm501_config_props {
+	char *name;
+	u32 shift;
+	u32 width;
+	enum prop_type prop_type;
+	enum val_type val_type;
+};
 
 #define MHZ (1000 * 1000)
 
@@ -1370,6 +1387,419 @@ static int sm501_init_dev(struct sm501_devdata *sm)
 	return 0;
 }
 
+static u32 lookup_str(const char *val, const char * const *list)
+{
+	u32 ret = 0;
+
+	while (*list) {
+		if (strcmp(val, *list) == 0)
+			return ret;
+		list++;
+		ret++;
+	}
+	return ~0;
+}
+
+static u32 lookup_num(u32 val, const u32 *list)
+{
+	u32 ret = 0;
+
+	while (*list != ~0) {
+		if (val == *list)
+			return ret;
+		list++;
+		ret++;
+	}
+	return ~0;
+}
+
+static const struct sm501_config_props misc_timming[] = {
+	{"ex",      28, 4, PROP_NUM, MT_EX},
+	{"xc",      24, 2, PROP_STR, MT_XC},
+	{"us",      23, 1, PROP_STR, ENDIS},
+	{"ssm1",    20, 1, PROP_STR, MT_SSM},
+	{"sm1",     16, 4, PROP_NUM, MT_SM},
+	{"ssm0",    12, 1, PROP_STR, MT_SSM},
+	{"sm0",      8, 4, PROP_NUM, MT_SM},
+	{"deb",      7, 1, PROP_STR, MT_DEBUG},
+	{"acpi",     6, 1, PROP_STR, ENDIS},
+	{"divider",  4, 2, PROP_NUM, MT_DIV},
+	{"usb-mode", 3, 1, PROP_STR, MT_USB},
+	{"delay",    0, 3, PROP_NUM, MT_DELAY},
+	{},
+};
+
+static const struct sm501_config_props misc_control[] = {
+	{"pad",      30, 2, PROP_NUM, MC_PAD},
+	{"usbclk",   28, 2, PROP_STR, MC_USBCLK},
+	{"uart-ssp", 27, 1, PROP_STR, MC_SSP},
+	{"lat",      26, 1, PROP_STR, ENDIS},
+	{"fp",       25, 1, PROP_NUM, MC_FP},
+	{"freq",     24, 1, PROP_NUM, MC_FREQ},
+	{"refresh",  21, 2, PROP_NUM, MC_REFRESH},
+	{"hold",     18, 3, PROP_NUM, MC_HOLD},
+	{"sh",       17, 1, PROP_STR, MC_SH},
+	{"ii",       16, 1, PROP_STR, MC_II},
+	{"pll",      15, 1, PROP_STR, ENDIS},
+	{"gap",      13, 2, PROP_STR, MC_GAP},
+	{"dac",      12, 1, PROP_STR, MC_DAC},
+	{"mc",       11, 1, PROP_STR, MC_MC},
+	{"bl",       10, 1, PROP_NUM, MC_BL},
+	{"usb",       9, 1, PROP_STR, MC_USB},
+	{"lb",        8, 1, PROP_STR, MC_LB},
+	{"vr",        4, 1, PROP_NUM, MC_VR},
+	{},
+};
+
+/* Read configuration values */
+static void sm501_of_read_config(struct device *dev, struct device_node *np,
+				 const char *prefix,
+				 const struct sm501_config_props *props,
+				 struct sm501_reg_init *ret)
+{
+	static const char * const endis[] = { "disable", "enable", NULL };
+	static const char * const xc[] = { "internal-pll", "hclk", "gpio33", NULL };
+	static const char * const ssm[] = { "288mhz", "div", NULL };
+	static const char * const debmode[] = { "input-reference", "output", NULL };
+	static const char * const usbmode[] = { "normal", "simulation", NULL };
+	static const char * const usbclk[] = { "crystal", "-", "96mhz", "48mhz", NULL };
+	static const char * const ssp[] = { "uart1", "ssp1", NULL };
+	static const char * const sh_ready[] = { "active-low", "active-high", NULL };
+	static const char * const int_invert[] = { "normal", "invert", NULL };
+	static const char * const slave[] = { "cpu", "8051", NULL };
+	static const char * const usbport[] = { "master", "slave", NULL };
+	static const char * const usbloop[] = { "normal", "loopback", NULL };
+
+	static const u32 divrate[] = { 336, 288, 240, 192, ~0 };
+	static const u32 fpdata[] = { 18, 24, ~0 };
+	static const u32 cfreq[] = { 24, 12, ~0 };
+	static const u32 bushold[] = { 0, 8, 16, 24, 32, ~0 };
+	static const u32 burst[] = { 8, 1, ~0 };
+	static const u32 vrmem[] = { 30, 62, ~0 };
+
+	struct device_node *child;
+	const char *sval;
+	u32 mask;
+	u32 val;
+	int err;
+
+	ret->mask = ~0;
+	ret->set = 0;
+
+	child = of_get_child_by_name(np, prefix);
+	if (!child)
+		return;
+
+	while (props->name) {
+		switch (props->prop_type) {
+		case PROP_NUM:
+			err = of_property_read_u32(child, props->name, &val);
+			break;
+		case PROP_STR:
+			err = of_property_read_string(child, props->name, &sval);
+			break;
+		}
+		if (!err) {
+			switch (props->val_type) {
+			case ENDIS:
+				val = lookup_str(sval, endis);
+				break;
+			case MT_EX:
+				val /= 16;
+				break;
+			case MT_XC:
+				val = lookup_str(sval, xc);
+				break;
+			case MT_SSM:
+				val = lookup_str(sval, ssm);
+				break;
+			case MT_SM:
+				if ((val % 3) == 0) {
+					val /= 3;
+					val = ffs(val);
+					val += 8;
+				} else {
+					val = ffs(val);
+				}
+				break;
+			case MT_DEBUG:
+				val = lookup_str(sval, debmode);
+				break;
+			case MT_DIV:
+				val = lookup_num(val, divrate);
+				break;
+			case MT_USB:
+				val = lookup_str(sval, usbmode);
+				break;
+			case MT_DELAY:
+				val /= 5;
+				break;
+			case MC_PAD:
+				val /= 8;
+				val = 2 - val;
+				break;
+			case MC_USBCLK:
+				val = lookup_str(sval, usbclk);
+				break;
+			case MC_SSP:
+				val = lookup_str(sval, ssp);
+				break;
+			case MC_FP:
+				val = lookup_num(val, fpdata);
+				break;
+			case MC_FREQ:
+				val = lookup_num(val, cfreq);
+				break;
+			case MC_REFRESH:
+				val = ffs(val) - 3;
+				break;
+			case MC_HOLD:
+				val = lookup_num(val, bushold);
+				break;
+			case MC_SH:
+				val = lookup_str(sval, sh_ready);
+				break;
+			case MC_II:
+				val = lookup_str(sval, int_invert);
+				break;
+			case MC_GAP:
+				if (!strcmp(sval, "default"))
+					val = 0;
+				else
+					val = ~0;
+				break;
+			case MC_DAC:
+				val = lookup_str(sval, endis) ^ 1;
+				break;
+			case MC_MC:
+				val = lookup_str(sval, slave);
+				break;
+			case MC_BL:
+				val = lookup_num(val, burst);
+				break;
+			case MC_USB:
+				val = lookup_str(sval, usbport);
+				break;
+			case MC_LB:
+				val = lookup_str(sval, usbloop);
+				break;
+			case MC_VR:
+				val = lookup_num(val, vrmem);
+				break;
+			}
+			mask = (1 << props->width) - 1;
+			if (mask >= val) {
+				mask = ~(mask << props->shift);
+				ret->mask &= mask;
+				ret->set |= val << props->shift;
+			} else {
+				switch (props->prop_type) {
+				case PROP_NUM:
+					dev_warn(dev, "%s invalid value %d",
+						 props->name, val);
+
+					break;
+				case PROP_STR:
+					dev_warn(dev, "%s invalid value %s",
+						 props->name, sval);
+					break;
+				}
+			}
+		}
+		props++;
+	}
+}
+
+/* Read GPIO control */
+/*
+ * DT example.
+ * gpio-pin-control {
+ *   pin@0 {
+ *	 gpio-port;
+ *   };
+ *   pin@1 {
+ *	 function;
+ *   };
+ * };
+ */
+static void sm501_of_read_gpio(struct device *dev, struct device_node *np,
+			       struct sm501_reg_init *hi, struct sm501_reg_init *low)
+{
+	struct device_node *gpio_group, *pin;
+	const char *prop_mode;
+	unsigned int pin_no;
+	int mode;
+	u64 mask;
+	u64 set;
+
+	mask = ~0;
+	set = 0;
+	gpio_group = of_get_child_by_name(np, "gpio-pin-control");
+	if (gpio_group) {
+		for_each_child_of_node(gpio_group, pin) {
+			mode = -1;
+			if (sscanf(pin->full_name, "pin@%u", &pin_no) == 1) {
+				if (of_property_read_bool(pin, "gpio-port"))
+					mode = 0;
+				else if (of_property_read_bool(pin, "function"))
+					mode = 1;
+			}
+			/* GPIO0 - 47 and 55 -63 */
+			if (mode < 0 ||
+			    (pin_no >= 64 || (pin_no >= 48 && pin_no <= 54))) {
+				dev_warn(dev,
+					 "%s mode %s is invalid.", pin->name, prop_mode);
+			} else {
+				mask &= ~(1 << pin_no);
+				set |= mode << pin_no;
+			}
+		}
+	}
+	hi->set = set >> 32;
+	low->set = set & 0xffffffff;
+	hi->mask = mask >> 32;
+	low->mask = mask & 0xffffffff;
+}
+
+static inline int read_i2c_prop(struct device *dev, struct device_node *child,
+				const char *name, u32 *val)
+{
+	if (of_property_read_u32(child, name, val)) {
+		dev_warn(dev, "%s/%s not found. skip it.", of_node_full_name(child), name);
+		return -ENOENT;
+	}
+	return 0;
+}
+
+/* Read GPIO I2C configuration */
+/*
+ * DT example.
+ * gpio-i2c {
+ *    i2c@0 {
+ *	sda = <gpio-pin>;
+ *	scl = <gpio-pin>;
+ *	delay = <delay>;
+ *	timeout = <timeout>;
+ *    };
+ *    i2c@1 {
+ *      :
+ *    };
+ *    :
+ * };
+ */
+static int sm501_parse_dt_gpio_i2c(struct device *dev, struct sm501_platdata *plat,
+				   struct device_node *np)
+{
+	struct device_node *i2c_group, *child;
+	unsigned int i;
+	u32 i2c_nr;
+	int err;
+
+	i2c_group = of_get_child_by_name(np, "gpio-i2c");
+	if (!i2c_group)
+		return 0;
+
+	i2c_nr = of_get_child_count(i2c_group);
+	plat->gpio_i2c = devm_kzalloc(dev, sizeof(*plat->gpio_i2c) * i2c_nr,
+				      GFP_KERNEL);
+	if (!plat->gpio_i2c)
+		return -ENOMEM;
+
+	plat->gpio_i2c_nr = i2c_nr;
+	i = 0;
+	for_each_child_of_node(i2c_group, child) {
+		u32 bus;
+
+		if (sscanf(child->full_name, "i2c@%u", &bus) != 1) {
+			dev_warn(dev, "Unknown address %s\n", child->name);
+			continue;
+		}
+
+		err = 0;
+		plat->gpio_i2c[i].bus_num = bus;
+		err += read_i2c_prop(dev, child, "sda", &plat->gpio_i2c[i].pin_sda);
+		err += read_i2c_prop(dev, child, "scl", &plat->gpio_i2c[i].pin_scl);
+		err += read_i2c_prop(dev, child, "delay", &plat->gpio_i2c[i].udelay);
+		err += read_i2c_prop(dev, child, "timeout", &plat->gpio_i2c[i].timeout);
+		if (err == 0)
+			i++;
+	}
+
+	return 0;
+}
+
+/* Read device functions */
+static u32 sm501_read_devices(struct device *dev, struct device_node *np)
+{
+	static const char * const funcname[] = {
+		"usb-host", "usb-slave", "ssp0", "ssp1",
+		"uart0", "uart1", "fbaccel", "ac97",
+		"i2s", "gpio",
+	};
+	struct property *prop;
+	unsigned int i;
+	const char *s;
+	u32 ret = 0;
+
+	of_property_for_each_string(np, "smi,devices", prop, s) {
+		for (i = 0; i < ARRAY_SIZE(funcname); i++) {
+			if (strcmp(s, funcname[i]) == 0) {
+				ret |= 1 << i;
+				goto next;
+			}
+		}
+		dev_warn(dev, "Unknown device function '%s'", s);
+next:
+	}
+	if (!ret)
+		dev_warn(dev, "devices not defined. disable all functions.");
+	return ret;
+}
+
+/* Build platform_data from OF property */
+struct plat_dt {
+	struct sm501_platdata plat;
+	struct sm501_initdata init;
+};
+
+static int sm501_parse_dt(struct sm501_devdata *sm, struct device_node *np)
+{
+	struct sm501_platdata *plat;
+	struct plat_dt *dt_p;
+	u32 word;
+	int ret;
+
+	dt_p = devm_kzalloc(sm->dev, sizeof(*dt_p), GFP_KERNEL);
+	if (!dt_p)
+		return -ENOMEM;
+
+	plat = &dt_p->plat;
+	plat->init = &dt_p->init;
+
+	plat->init->devices = sm501_read_devices(sm->dev, np);
+	/* mclk and m1xclk are not u32, so convert between them using intermediate variables. */
+	of_property_read_u32(np, "smi,mclk", &word);
+	plat->init->mclk = word;
+	of_property_read_u32(np, "smi,m1xclk", &word);
+	plat->init->m1xclk = word;
+
+	sm501_of_read_config(sm->dev, np, "misc-timing", misc_timming,
+			     &plat->init->misc_timing);
+	sm501_of_read_config(sm->dev, np, "misc-control", misc_control,
+			     &plat->init->misc_control);
+	sm501_of_read_gpio(sm->dev, np,
+			   &plat->init->gpio_high, &plat->init->gpio_low);
+
+	if (IS_ENABLED(CONFIG_MFD_SM501_GPIO) &&
+	    (plat->init->devices & SM501_USE_GPIO)) {
+		ret = sm501_parse_dt_gpio_i2c(sm->dev, plat, np);
+		if (ret)
+			return ret;
+	}
+	sm->platdata = plat;
+	return 0;
+}
+
 static int sm501_plat_probe(struct platform_device *dev)
 {
 	struct sm501_devdata *sm;
@@ -1406,6 +1836,12 @@ static int sm501_plat_probe(struct platform_device *dev)
 		goto err_res;
 	}
 
+	if (IS_ENABLED(CONFIG_OF) && dev->dev.of_node) {
+		ret = sm501_parse_dt(sm, dev->dev.of_node);
+		if (ret)
+			goto err_res;
+	}
+
 	platform_set_drvdata(dev, sm);
 
 	sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
diff --git a/drivers/video/fbdev/sm501fb.c b/drivers/video/fbdev/sm501fb.c
index d6fdc1737cd2..5de00f2570aa 100644
--- a/drivers/video/fbdev/sm501fb.c
+++ b/drivers/video/fbdev/sm501fb.c
@@ -1932,6 +1932,106 @@ static int sm501fb_start_one(struct sm501fb_info *info,
 	return 0;
 }
 
+#if defined(CONFIG_OF)
+static u32 read_display_flags(struct device_node *np)
+{
+	static const char * const name[] = {
+		"use-init-done", "disable-at-exit", "use-hwcursor", "use-hwaccel",
+		"panel-no-fpen", "panel-no-vbiasen", "panel-inv-fpen", "panel-inv-vbiasen",
+	};
+
+	struct property *prop;
+	unsigned int i;
+	const char *s;
+	u32 ret = 0;
+
+	of_property_for_each_string(np, "smi,flags", prop, s) {
+		for (i = 0; i < ARRAY_SIZE(name); i++) {
+			if (strcmp(s, name[i]) == 0) {
+				ret |= 1 << i;
+				break;
+			}
+		}
+	}
+	return ret;
+}
+
+/* parse CRT / panel configuration */
+static struct sm501_platdata_fbsub *dt_fbsub(struct device *dev,
+					     struct device_node *np,
+					     const char *name)
+{
+	struct sm501_platdata_fbsub *fbsub = NULL;
+	struct fb_videomode *def_mode = NULL;
+	struct device_node *child;
+	const void *p_edid;
+	u32 flags = 0;
+	u32 bpp = 0;
+	int len;
+
+	child = of_get_child_by_name(np, name);
+	if (child == NULL)
+		return NULL;
+
+	p_edid = of_get_property(child, "edid", &len);
+	if (p_edid && len == EDID_LENGTH) {
+		struct fb_monspecs *specs;
+		u8 *edid;
+
+		edid = kmemdup(p_edid, EDID_LENGTH, GFP_KERNEL);
+		if (edid) {
+			specs = kzalloc(sizeof(*specs), GFP_KERNEL);
+			if (specs) {
+				fb_edid_to_monspecs(edid, specs);
+				def_mode = specs->modedb;
+			}
+		}
+		kfree(edid);
+	}
+
+	of_property_read_u32(child, "bpp", &bpp);
+
+	/* If flags property is obtained, fbsub is returned. */
+	flags = read_display_flags(child);
+	if (flags) {
+		fbsub = devm_kzalloc(dev, sizeof(*fbsub), GFP_KERNEL);
+		if (fbsub) {
+			fbsub->def_mode = def_mode;
+			fbsub->def_bpp = bpp;
+			fbsub->flags = flags;
+		}
+	}
+	return fbsub;
+}
+
+/* Build platform_data from OF property */
+static struct sm501_platdata_fb *pdata_from_dt(struct device *dev, struct device_node *np)
+{
+	enum sm501_fb_routing fb_route = SM501_FB_OWN;
+	struct sm501_platdata_fb *pdata = NULL;
+	struct sm501_platdata_fbsub *fb_crt;
+	struct sm501_platdata_fbsub *fb_pnl;
+	unsigned int flags = 0;
+
+	if (of_property_read_bool(np, "route-crt-panel"))
+		fb_route = SM501_FB_CRT_PANEL;
+	if (of_property_read_bool(np, "swap-fb-endian"))
+		flags = SM501_FBPD_SWAP_FB_ENDIAN;
+	fb_crt = dt_fbsub(dev, np, "crt");
+	fb_pnl = dt_fbsub(dev, np, "panel");
+	if (fb_crt || fb_pnl) {
+		pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+		if (pdata) {
+			pdata->fb_route = fb_route;
+			pdata->flags = flags;
+			pdata->fb_crt = fb_crt;
+			pdata->fb_pnl = fb_pnl;
+		}
+	}
+	return pdata;
+}
+#endif
+
 static int sm501fb_probe(struct platform_device *pdev)
 {
 	struct sm501fb_info *info;
@@ -1974,6 +2074,12 @@ static int sm501fb_probe(struct platform_device *pdev)
 				if (info->edid_data)
 					found = 1;
 			}
+			/* Get platform data compatible configuration */
+			if (!found) {
+				info->pdata = pdata_from_dt(dev, np);
+				if (info->pdata)
+					found = 1;
+			}
 		}
 #endif
 		if (!found) {
-- 
2.39.2


  parent reply	other threads:[~2024-01-09  8:24 UTC|newest]

Thread overview: 138+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-09  8:22 [DO NOT MERGE v6 00/37] Device Tree support for SH7751 based board Yoshinori Sato
2024-01-09  8:22 ` Yoshinori Sato
2024-01-09  8:22 ` [DO NOT MERGE v6 01/37] sh: passing FDT address to kernel startup Yoshinori Sato
2024-01-09  8:22   ` Yoshinori Sato
2024-01-15 14:03   ` Geert Uytterhoeven
2024-01-15 14:03     ` Geert Uytterhoeven
2024-01-09  8:22 ` [DO NOT MERGE v6 02/37] sh: Kconfig unified OF supported targets Yoshinori Sato
2024-01-09  8:22   ` Yoshinori Sato
2024-02-26 16:21   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 03/37] sh: Enable OF support for build and configuration Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 04/37] dt-bindings: interrupt-controller: Add header for Renesas SH3/4 INTC Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 18:41   ` Krzysztof Kozlowski
2024-01-09 18:41     ` Krzysztof Kozlowski
2024-01-09  8:23 ` [DO NOT MERGE v6 05/37] sh: GENERIC_IRQ_CHIP support for CONFIG_OF=y Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 06/37] sh: kernel/setup Update DT support Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 07/37] sh: Fix COMMON_CLK support in CONFIG_OF=y Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 08/37] clocksource: sh_tmu: CLOCKSOURCE support Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-26 16:54   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas,tmu: add renesas,tmu-sh7750 Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas, tmu: add renesas, tmu-sh7750 Yoshinori Sato
2024-01-15 13:59   ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas,tmu: add renesas,tmu-sh7750 Geert Uytterhoeven
2024-01-15 13:59     ` [DO NOT MERGE v6 09/37] dt-bindings: timer: renesas, tmu: add renesas, tmu-sh7750 Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 10/37] sh: Common PCI Framework driver support Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 11/37] pci: pci-sh7751: Add SH7751 PCI driver Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 12/37] dt-bindings: pci: pci-sh7751: Add SH7751 PCI Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 12:42   ` Linus Walleij
2024-01-09 12:42     ` Linus Walleij
2024-01-09 17:31     ` Rob Herring
2024-01-09 17:31       ` Rob Herring
2024-01-09  8:23 ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas, sh7750-cpg header Yoshinori Sato
2024-02-27 16:47   ` [DO NOT MERGE v6 13/37] dt-bindings: clock: sh7750-cpg: Add renesas,sh7750-cpg header Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 14/37] clk: Compatible with narrow registers Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-27 15:41   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 15/37] clk: renesas: Add SH7750/7751 CPG Driver Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-27 16:34   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 16/37] irqchip: Add SH7751 INTC driver Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: Add json-schema Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas, sh7751-intc: " Yoshinori Sato
2024-01-09 12:30   ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: " Linus Walleij
2024-01-09 12:30     ` Linus Walleij
2024-01-17  9:46     ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas, sh7751-intc: " Yoshinori Sato
2024-01-17  9:46       ` [DO NOT MERGE v6 17/37] dt-bindings: interrupt-controller: renesas,sh7751-intc: " Yoshinori Sato
2024-01-17 10:06       ` Geert Uytterhoeven
2024-01-17 10:06         ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 18/37] irqchip: SH7751 external interrupt encoder with enable gate Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: Add json-schema Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas, sh7751-irl-ext: " Yoshinori Sato
2024-01-09 16:29   ` [DO NOT MERGE v6 19/37] dt-bindings: interrupt-controller: renesas,sh7751-irl-ext: " Rob Herring
2024-01-09 16:29     ` Rob Herring
2024-01-09 17:18   ` Rob Herring
2024-01-09 17:18     ` Rob Herring
2024-01-09  8:23 ` [DO NOT MERGE v6 20/37] serial: sh-sci: fix SH4 OF support Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas,scif: Add scif-sh7751 Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas, scif: " Yoshinori Sato
2024-01-15  9:29   ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas,scif: " Geert Uytterhoeven
2024-01-15  9:29     ` [DO NOT MERGE v6 21/37] dt-bindings: serial: renesas, scif: " Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi,sm501: SMI SM501 binding json-schema Yoshinori Sato
2024-01-09  8:23   ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi, sm501: " Yoshinori Sato
2024-01-15  9:52   ` [DO NOT MERGE v6 22/37] dt-bindings: display: smi,sm501: " Geert Uytterhoeven
2024-01-15  9:52     ` Geert Uytterhoeven
2024-01-09  8:23 ` Yoshinori Sato [this message]
2024-01-09  8:23   ` [DO NOT MERGE v6 23/37] mfd: sm501: Convert platform_data to OF property Yoshinori Sato
2024-01-11 11:35   ` Lee Jones
2024-01-11 11:35     ` Lee Jones
2024-01-09  8:23 ` [DO NOT MERGE v6 24/37] dt-binding: sh: cpus: Add SH CPUs json-schema Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 18:00   ` Conor Dooley
2024-01-09 18:00     ` Conor Dooley
2024-01-09  8:23 ` [DO NOT MERGE v6 25/37] dt-bindings: vendor-prefixes: Add iodata Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 18:03   ` Conor Dooley
2024-01-09 18:03     ` Conor Dooley
2024-01-15 14:02   ` Geert Uytterhoeven
2024-01-15 14:02     ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 26/37] dt-bindings: vendor-prefixes: Add smi Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 18:05   ` Conor Dooley
2024-01-09 18:05     ` Conor Dooley
2024-01-10 11:23     ` Geert Uytterhoeven
2024-01-10 11:23       ` Geert Uytterhoeven
2024-01-10 14:28       ` Guenter Roeck
2024-01-10 14:28         ` Guenter Roeck
2024-01-10 16:11       ` Conor Dooley
2024-01-10 16:11         ` Conor Dooley
2024-01-11 14:59         ` Rob Herring
2024-01-11 14:59           ` Rob Herring
2024-01-09 21:40   ` Uwe Kleine-König
2024-01-09 21:40     ` Uwe Kleine-König
2024-01-09  8:23 ` [DO NOT MERGE v6 27/37] dt-bindings: ata: ata-generic: Add new targets Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09 18:07   ` Conor Dooley
2024-01-09 18:07     ` Conor Dooley
2024-01-09 18:09     ` Conor Dooley
2024-01-09 18:09       ` Conor Dooley
2024-01-10  2:06   ` Damien Le Moal
2024-01-10  2:06     ` Damien Le Moal
2024-01-10  7:19     ` Krzysztof Kozlowski
2024-01-10  7:19       ` Krzysztof Kozlowski
2024-01-10  7:25       ` Damien Le Moal
2024-01-10  7:25         ` Damien Le Moal
2024-01-09  8:23 ` [DO NOT MERGE v6 28/37] dt-bindings: soc: renesas: sh: Add SH7751 based target Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-27 15:58   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 29/37] sh: SH7751R SoC Internal peripheral definition dtsi Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 30/37] sh: add RTS7751R2D Plus DTS Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 31/37] sh: Add IO DATA LANDISK dts Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 32/37] sh: Add IO DATA USL-5P dts Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 33/37] sh: j2_mimas_v2.dts update Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-27 16:07   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 34/37] sh: Add dtbs target support Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-02-27 18:48   ` Geert Uytterhoeven
2024-01-09  8:23 ` [DO NOT MERGE v6 35/37] sh: RTS7751R2D Plus OF defconfig Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 36/37] sh: LANDISK " Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato
2024-01-09  8:23 ` [DO NOT MERGE v6 37/37] sh: j2_defconfig: update Yoshinori Sato
2024-01-09  8:23   ` Yoshinori Sato

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=569f0bfb4fa3fcec8fbd64f67fc4fd2d1cba3f77.1704788539.git.ysato@users.sourceforge.jp \
    --to=ysato@users.sourceforge.jp \
    --cc=42.hyeyoo@gmail.com \
    --cc=airlied@gmail.com \
    --cc=akpm@linux-foundation.org \
    --cc=arnd@arndb.de \
    --cc=azeemshaikh38@gmail.com \
    --cc=bhe@redhat.com \
    --cc=bhelgaas@google.com \
    --cc=biju.das.jz@bp.renesas.com \
    --cc=bmeng@tinylab.org \
    --cc=conor+dt@kernel.org \
    --cc=corbet@lwn.net \
    --cc=dalias@libc.org \
    --cc=daniel.lezcano@linaro.org \
    --cc=daniel@ffwll.ch \
    --cc=deller@gmx.de \
    --cc=devicetree@vger.kernel.org \
    --cc=dlemoal@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=forbidden405@foxmail.com \
    --cc=geert+renesas@glider.be \
    --cc=glaubitz@physik.fu-berlin.de \
    --cc=gregkh@linuxfoundation.org \
    --cc=heiko@sntech.de \
    --cc=javierm@redhat.com \
    --cc=jcmvbkbc@gmail.com \
    --cc=jernej.skrabec@gmail.com \
    --cc=jirislaby@kernel.org \
    --cc=kernel@mkarcher.dialup.fu-berlin.de \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=kw@linux.com \
    --cc=laurent.pinchart+renesas@ideasonboard.com \
    --cc=lee@kernel.org \
    --cc=linus.walleij@linaro.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-fbdev@vger.kernel.org \
    --cc=linux-ide@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=linux-renesas-soc@vger.kernel.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=linux-sh@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=lpieralisi@kernel.org \
    --cc=lukas.bulwahn@gmail.com \
    --cc=maarten.lankhorst@linux.intel.com \
    --cc=macromorgan@hotmail.com \
    --cc=magnus.damm@gmail.com \
    --cc=mripard@kernel.org \
    --cc=mturquette@baylibre.com \
    --cc=palmer@rivosinc.com \
    --cc=rdunlap@infradead.org \
    --cc=rientjes@google.com \
    --cc=robh+dt@kernel.org \
    --cc=s.shtylyov@omp.ru \
    --cc=sam@ravnborg.org \
    --cc=sboyd@kernel.org \
    --cc=sfr@canb.auug.org.au \
    --cc=sre@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tzimmermann@suse.de \
    --cc=u.kleine-koenig@pengutronix.de \
    --cc=vbabka@suse.cz \
    --cc=ychuang3@nuvoton.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.