@@ -20,6 +20,17 @@ Optional properties:
set different foreign endian.
- big-endian: available on little endian systems, to
set different foreign endian.
+- sm501,devices: select peripheral functions.
+ available usb-host, usb-gadget, ssp0, ssp,1 uart0, uart1, accel,
+ ac97, i2s, gpio and all.
+- sm501,mclk: SM501 mclk frequency.
+- sm501,m1xclk: SM501 m1xclk frequency.
+- sm501,misc-timing: SM501 Miscellaneous Timing reg value.
+- sm501,misc-control: SM501 Miscellaneous Control reg value.
+- sm501,gpio-low: SM501 GPIO31-0 Control reg value.
+- sm501,gpio-high: SM501 GPIO63-32 Control reg value.
+- sm501,num-i2c: I2C channel number.
+- sm501,gpio-i2c: I2C assigned GPIO.
Example for MPC5200:
display@1,0 {
@@ -80,6 +80,9 @@ struct sm501_devdata {
unsigned int irq;
void __iomem *regs;
unsigned int rev;
+#if defined(CONFIG_OF)
+ struct device_node *np;
+#endif
};
@@ -1370,6 +1373,106 @@ static int sm501_init_dev(struct sm501_devdata *sm)
return 0;
}
+static unsigned int sm501_parse_devices_str(const char *str)
+{
+ char *sep;
+ unsigned int device = 0;
+ int i;
+ int len;
+ static const struct {
+ char *devname;
+ unsigned int devid;
+ } devlist[] = {
+ { "usb-host", SM501_USE_USB_HOST },
+ { "usb-gadget", SM501_USE_USB_SLAVE },
+ { "ssp0", SM501_USE_SSP0 },
+ { "ssp1", SM501_USE_SSP1 },
+ { "uart0", SM501_USE_UART0 },
+ { "uart1", SM501_USE_UART1 },
+ { "accel", SM501_USE_FBACCEL },
+ { "ac97", SM501_USE_AC97 },
+ { "i2s", SM501_USE_I2S },
+ { "gpio", SM501_USE_GPIO },
+ { "all", SM501_USE_ALL },
+ };
+
+ do {
+ sep = strchr(str, ',');
+ len = sep ? sep - str : strlen(str);
+ for (i = 0; i < ARRAY_SIZE(devlist); i++) {
+ if (strncasecmp(str, devlist[i].devname, len) == 0) {
+ device |= devlist[i].devid;
+ break;
+ }
+ }
+ str = sep + 1;
+ } while (sep);
+ return device;
+}
+
+#if defined(CONFIG_OF)
+static void sm501_of_read_reg_init(struct sm501_devdata *sm,
+ const char *propname, struct sm501_reg_init *val)
+{
+ u32 u32_val;
+
+ if (!of_property_read_u32_index(sm->np, propname, 0, &u32_val))
+ val->set = u32_val;
+ if (!of_property_read_u32_index(sm->np, propname, 1, &u32_val))
+ val->mask = u32_val;
+}
+
+static int sm501_parse_dt(struct sm501_devdata *sm)
+{
+ struct sm501_platdata *plat;
+ const char *devstr;
+ u32 u32_val;
+
+ if (sm->np == NULL)
+ return 0;
+ plat = kzalloc(sizeof(struct sm501_platdata), GFP_KERNEL);
+ if (plat == NULL)
+ return -ENOMEM;
+ plat->init = kzalloc(sizeof(struct sm501_initdata), GFP_KERNEL);
+ if (plat->init == NULL)
+ goto err;
+
+ if (!of_property_read_string(sm->np, "sm501,devices", &devstr))
+ plat->init->devices = sm501_parse_devices_str(devstr);
+ if (!of_property_read_u32_index(sm->np, "sm501,mclk", 0, &u32_val))
+ plat->init->mclk = u32_val;
+ if (!of_property_read_u32_index(sm->np, "sm501,m1xclk", 0, &u32_val))
+ plat->init->m1xclk = u32_val;
+ sm501_of_read_reg_init(sm, "sm501,misc-timing", &plat->init->misc_timing);
+ sm501_of_read_reg_init(sm, "sm501,misc-control", &plat->init->misc_control);
+ sm501_of_read_reg_init(sm, "sm501,gpio-low", &plat->init->gpio_low);
+ sm501_of_read_reg_init(sm, "sm501,gpio-high", &plat->init->gpio_high);
+
+#ifdef CONFIG_MFD_SM501_GPIO
+ if (plat->init->devices & SM501_USE_GPIO) {
+ if (!of_property_read_u32_index(sm->np, "sm501,num-i2c", 0, &u32_val))
+ plat->gpio_i2c_nr = u32_val;
+ }
+ if (plat->gpio_i2c_nr > 0) {
+ plat->gpio_i2c = kcalloc(plat->gpio_i2c_nr,
+ sizeof(struct sm501_platdata_gpio_i2c),
+ GFP_KERNEL);
+ if (plat->gpio_i2c == NULL)
+ goto err;
+ of_property_read_variable_u32(sm->np, "sm501,gpio-i2c",
+ plat->gpio_i2c,
+ plat->gpio_i2c_nr * 5);
+ }
+#endif
+ sm->platdata = plat;
+ return 0;
+err:
+ kfree(plat->init);
+ kfree(plat);
+ return -ENOMEM;
+}
+#endif
+
static int sm501_plat_probe(struct platform_device *dev)
{
struct sm501_devdata *sm;
@@ -1384,7 +1487,6 @@ static int sm501_plat_probe(struct platform_device *dev)
sm->dev = &dev->dev;
sm->pdev_id = dev->id;
sm->platdata = dev_get_platdata(&dev->dev);
-
ret = platform_get_irq(dev, 0);
if (ret < 0)
goto err_res;
@@ -1406,6 +1508,15 @@ static int sm501_plat_probe(struct platform_device *dev)
goto err_res;
}
+#if defined(CONFIG_OF)
+ if (dev->dev.of_node) {
+ sm->np = dev->dev.of_node;
+ ret = sm501_parse_dt(sm);
+ if (ret)
+ goto err_res;
+ }
+#endif
+
platform_set_drvdata(dev, sm);
sm->regs = ioremap(sm->io_res->start, resource_size(sm->io_res));
Some parameters only platform_device. Added same parameters in OF property. Signed-off-by: Yoshinori Sato <ysato@users.sourceforge.jp> --- .../devicetree/bindings/display/sm501fb.txt | 11 ++ drivers/mfd/sm501.c | 113 +++++++++++++++++- 2 files changed, 123 insertions(+), 1 deletion(-)