Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'imx-weim-3.12' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

From Shawn Guo:
This is a patch series that updates imx-weim bus driver to have it
support more i.MX SoCs. Because there is no maintainer for
drivers/bus so far, I'm forwarding it through IMX tree for 3.12 merge
window.

* tag 'imx-weim-3.12' of git://git.linaro.org/people/shawnguo/linux-2.6:
drivers: bus: imx-weim: Add support for i.MX1/21/25/27/31/35/50/51/53
drivers: bus: imx-weim: Add missing platform_driver.owner field
drivers: bus: imx-weim: use module_platform_driver_probe()
drivers: bus: imx-weim: Simplify error path
drivers: bus: imx-weim: Remove private driver data

+87 -62
+12 -5
Documentation/devicetree/bindings/bus/imx-weim.txt
··· 8 8 9 9 Required properties: 10 10 11 - - compatible: Should be set to "fsl,imx6q-weim" 11 + - compatible: Should be set to "fsl,<soc>-weim" 12 12 - reg: A resource specifier for the register space 13 13 (see the example below) 14 14 - clocks: the clock, see the example below. ··· 21 21 22 22 Timing property for child nodes. It is mandatory, not optional. 23 23 24 - - fsl,weim-cs-timing: The timing array, contains 6 timing values for the 24 + - fsl,weim-cs-timing: The timing array, contains timing values for the 25 25 child node. We can get the CS index from the child 26 - node's "reg" property. This property contains the values 27 - for the registers EIM_CSnGCR1, EIM_CSnGCR2, EIM_CSnRCR1, 28 - EIM_CSnRCR2, EIM_CSnWCR1, EIM_CSnWCR2 in this order. 26 + node's "reg" property. The number of registers depends 27 + on the selected chip. 28 + For i.MX1, i.MX21 ("fsl,imx1-weim") there are two 29 + registers: CSxU, CSxL. 30 + For i.MX25, i.MX27, i.MX31 and i.MX35 ("fsl,imx27-weim") 31 + there are three registers: CSCRxU, CSCRxL, CSCRxA. 32 + For i.MX50, i.MX53 ("fsl,imx50-weim"), 33 + i.MX51 ("fsl,imx51-weim") and i.MX6Q ("fsl,imx6q-weim") 34 + there are six registers: CSxGCR1, CSxGCR2, CSxRCR1, 35 + CSxRCR2, CSxWCR1, CSxWCR2. 29 36 30 37 Example for an imx6q-sabreauto board, the NOR flash connected to the WEIM: 31 38
+1 -2
drivers/bus/Kconfig
··· 8 8 bool "Freescale EIM DRIVER" 9 9 depends on ARCH_MXC 10 10 help 11 - Driver for i.MX6 WEIM controller. 11 + Driver for i.MX WEIM controller. 12 12 The WEIM(Wireless External Interface Module) works like a bus. 13 13 You can attach many different devices on it, such as NOR, onenand. 14 - But now, we only support the Parallel NOR. 15 14 16 15 config MVEBU_MBUS 17 16 bool
+74 -55
drivers/bus/imx-weim.c
··· 12 12 #include <linux/io.h> 13 13 #include <linux/of_device.h> 14 14 15 - struct imx_weim { 16 - void __iomem *base; 17 - struct clk *clk; 15 + struct imx_weim_devtype { 16 + unsigned int cs_count; 17 + unsigned int cs_regs_count; 18 + unsigned int cs_stride; 19 + }; 20 + 21 + static const struct imx_weim_devtype imx1_weim_devtype = { 22 + .cs_count = 6, 23 + .cs_regs_count = 2, 24 + .cs_stride = 0x08, 25 + }; 26 + 27 + static const struct imx_weim_devtype imx27_weim_devtype = { 28 + .cs_count = 6, 29 + .cs_regs_count = 3, 30 + .cs_stride = 0x10, 31 + }; 32 + 33 + static const struct imx_weim_devtype imx50_weim_devtype = { 34 + .cs_count = 4, 35 + .cs_regs_count = 6, 36 + .cs_stride = 0x18, 37 + }; 38 + 39 + static const struct imx_weim_devtype imx51_weim_devtype = { 40 + .cs_count = 6, 41 + .cs_regs_count = 6, 42 + .cs_stride = 0x18, 18 43 }; 19 44 20 45 static const struct of_device_id weim_id_table[] = { 21 - { .compatible = "fsl,imx6q-weim", }, 22 - {} 46 + /* i.MX1/21 */ 47 + { .compatible = "fsl,imx1-weim", .data = &imx1_weim_devtype, }, 48 + /* i.MX25/27/31/35 */ 49 + { .compatible = "fsl,imx27-weim", .data = &imx27_weim_devtype, }, 50 + /* i.MX50/53/6Q */ 51 + { .compatible = "fsl,imx50-weim", .data = &imx50_weim_devtype, }, 52 + { .compatible = "fsl,imx6q-weim", .data = &imx50_weim_devtype, }, 53 + /* i.MX51 */ 54 + { .compatible = "fsl,imx51-weim", .data = &imx51_weim_devtype, }, 55 + { } 23 56 }; 24 57 MODULE_DEVICE_TABLE(of, weim_id_table); 25 58 26 - #define CS_TIMING_LEN 6 27 - #define CS_REG_RANGE 0x18 28 - 29 59 /* Parse and set the timing for this device. */ 30 - static int 31 - weim_timing_setup(struct platform_device *pdev, struct device_node *np) 60 + static int __init weim_timing_setup(struct device_node *np, void __iomem *base, 61 + const struct imx_weim_devtype *devtype) 32 62 { 33 - struct imx_weim *weim = platform_get_drvdata(pdev); 34 - u32 value[CS_TIMING_LEN]; 35 - u32 cs_idx; 36 - int ret; 37 - int i; 63 + u32 cs_idx, value[devtype->cs_regs_count]; 64 + int i, ret; 38 65 39 66 /* get the CS index from this child node's "reg" property. */ 40 67 ret = of_property_read_u32(np, "reg", &cs_idx); 41 68 if (ret) 42 69 return ret; 43 70 44 - /* The weim has four chip selects. */ 45 - if (cs_idx > 3) 71 + if (cs_idx >= devtype->cs_count) 46 72 return -EINVAL; 47 73 48 74 ret = of_property_read_u32_array(np, "fsl,weim-cs-timing", 49 - value, CS_TIMING_LEN); 75 + value, devtype->cs_regs_count); 50 76 if (ret) 51 77 return ret; 52 78 53 79 /* set the timing for WEIM */ 54 - for (i = 0; i < CS_TIMING_LEN; i++) 55 - writel(value[i], weim->base + cs_idx * CS_REG_RANGE + i * 4); 80 + for (i = 0; i < devtype->cs_regs_count; i++) 81 + writel(value[i], base + cs_idx * devtype->cs_stride + i * 4); 82 + 56 83 return 0; 57 84 } 58 85 59 - static int weim_parse_dt(struct platform_device *pdev) 86 + static int __init weim_parse_dt(struct platform_device *pdev, 87 + void __iomem *base) 60 88 { 89 + const struct of_device_id *of_id = of_match_device(weim_id_table, 90 + &pdev->dev); 91 + const struct imx_weim_devtype *devtype = of_id->data; 61 92 struct device_node *child; 62 93 int ret; 63 94 ··· 96 65 if (!child->name) 97 66 continue; 98 67 99 - ret = weim_timing_setup(pdev, child); 68 + ret = weim_timing_setup(child, base, devtype); 100 69 if (ret) { 101 70 dev_err(&pdev->dev, "%s set timing failed.\n", 102 71 child->full_name); ··· 111 80 return ret; 112 81 } 113 82 114 - static int weim_probe(struct platform_device *pdev) 83 + static int __init weim_probe(struct platform_device *pdev) 115 84 { 116 - struct imx_weim *weim; 117 85 struct resource *res; 118 - int ret = -EINVAL; 119 - 120 - weim = devm_kzalloc(&pdev->dev, sizeof(*weim), GFP_KERNEL); 121 - if (!weim) { 122 - ret = -ENOMEM; 123 - goto weim_err; 124 - } 125 - platform_set_drvdata(pdev, weim); 86 + struct clk *clk; 87 + void __iomem *base; 88 + int ret; 126 89 127 90 /* get the resource */ 128 91 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 129 - weim->base = devm_ioremap_resource(&pdev->dev, res); 130 - if (IS_ERR(weim->base)) { 131 - ret = PTR_ERR(weim->base); 132 - goto weim_err; 133 - } 92 + base = devm_ioremap_resource(&pdev->dev, res); 93 + if (IS_ERR(base)) 94 + return PTR_ERR(base); 134 95 135 96 /* get the clock */ 136 - weim->clk = devm_clk_get(&pdev->dev, NULL); 137 - if (IS_ERR(weim->clk)) 138 - goto weim_err; 97 + clk = devm_clk_get(&pdev->dev, NULL); 98 + if (IS_ERR(clk)) 99 + return PTR_ERR(clk); 139 100 140 - ret = clk_prepare_enable(weim->clk); 101 + ret = clk_prepare_enable(clk); 141 102 if (ret) 142 - goto weim_err; 103 + return ret; 143 104 144 105 /* parse the device node */ 145 - ret = weim_parse_dt(pdev); 146 - if (ret) { 147 - clk_disable_unprepare(weim->clk); 148 - goto weim_err; 149 - } 106 + ret = weim_parse_dt(pdev, base); 107 + if (ret) 108 + clk_disable_unprepare(clk); 109 + else 110 + dev_info(&pdev->dev, "Driver registered.\n"); 150 111 151 - dev_info(&pdev->dev, "WEIM driver registered.\n"); 152 - return 0; 153 - 154 - weim_err: 155 112 return ret; 156 113 } 157 114 158 115 static struct platform_driver weim_driver = { 159 116 .driver = { 160 - .name = "imx-weim", 161 - .of_match_table = weim_id_table, 117 + .name = "imx-weim", 118 + .owner = THIS_MODULE, 119 + .of_match_table = weim_id_table, 162 120 }, 163 - .probe = weim_probe, 164 121 }; 122 + module_platform_driver_probe(weim_driver, weim_probe); 165 123 166 - module_platform_driver(weim_driver); 167 124 MODULE_AUTHOR("Freescale Semiconductor Inc."); 168 125 MODULE_DESCRIPTION("i.MX EIM Controller Driver"); 169 126 MODULE_LICENSE("GPL");