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

Configure Feed

Select the types of activity you want to include in your feed.

at v4.16-rc1 186 lines 4.5 kB view raw
1/* 2 * Copyright (C) 2014 Free Electrons 3 * 4 * License Terms: GNU General Public License v2 5 * Author: Boris BREZILLON <boris.brezillon@free-electrons.com> 6 * 7 * Allwinner PRCM (Power/Reset/Clock Management) driver 8 * 9 */ 10 11#include <linux/mfd/core.h> 12#include <linux/init.h> 13#include <linux/of.h> 14 15#define SUN8I_CODEC_ANALOG_BASE 0x1c0 16#define SUN8I_CODEC_ANALOG_SIZE 0x4 17 18struct prcm_data { 19 int nsubdevs; 20 const struct mfd_cell *subdevs; 21}; 22 23static const struct resource sun6i_a31_ar100_clk_res[] = { 24 { 25 .start = 0x0, 26 .end = 0x3, 27 .flags = IORESOURCE_MEM, 28 }, 29}; 30 31static const struct resource sun6i_a31_apb0_clk_res[] = { 32 { 33 .start = 0xc, 34 .end = 0xf, 35 .flags = IORESOURCE_MEM, 36 }, 37}; 38 39static const struct resource sun6i_a31_apb0_gates_clk_res[] = { 40 { 41 .start = 0x28, 42 .end = 0x2b, 43 .flags = IORESOURCE_MEM, 44 }, 45}; 46 47static const struct resource sun6i_a31_ir_clk_res[] = { 48 { 49 .start = 0x54, 50 .end = 0x57, 51 .flags = IORESOURCE_MEM, 52 }, 53}; 54 55static const struct resource sun6i_a31_apb0_rstc_res[] = { 56 { 57 .start = 0xb0, 58 .end = 0xb3, 59 .flags = IORESOURCE_MEM, 60 }, 61}; 62 63static const struct resource sun8i_codec_analog_res[] = { 64 DEFINE_RES_MEM(SUN8I_CODEC_ANALOG_BASE, SUN8I_CODEC_ANALOG_SIZE), 65}; 66 67static const struct mfd_cell sun6i_a31_prcm_subdevs[] = { 68 { 69 .name = "sun6i-a31-ar100-clk", 70 .of_compatible = "allwinner,sun6i-a31-ar100-clk", 71 .num_resources = ARRAY_SIZE(sun6i_a31_ar100_clk_res), 72 .resources = sun6i_a31_ar100_clk_res, 73 }, 74 { 75 .name = "sun6i-a31-apb0-clk", 76 .of_compatible = "allwinner,sun6i-a31-apb0-clk", 77 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res), 78 .resources = sun6i_a31_apb0_clk_res, 79 }, 80 { 81 .name = "sun6i-a31-apb0-gates-clk", 82 .of_compatible = "allwinner,sun6i-a31-apb0-gates-clk", 83 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res), 84 .resources = sun6i_a31_apb0_gates_clk_res, 85 }, 86 { 87 .name = "sun6i-a31-ir-clk", 88 .of_compatible = "allwinner,sun4i-a10-mod0-clk", 89 .num_resources = ARRAY_SIZE(sun6i_a31_ir_clk_res), 90 .resources = sun6i_a31_ir_clk_res, 91 }, 92 { 93 .name = "sun6i-a31-apb0-clock-reset", 94 .of_compatible = "allwinner,sun6i-a31-clock-reset", 95 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res), 96 .resources = sun6i_a31_apb0_rstc_res, 97 }, 98}; 99 100static const struct mfd_cell sun8i_a23_prcm_subdevs[] = { 101 { 102 .name = "sun8i-a23-apb0-clk", 103 .of_compatible = "allwinner,sun8i-a23-apb0-clk", 104 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_clk_res), 105 .resources = sun6i_a31_apb0_clk_res, 106 }, 107 { 108 .name = "sun6i-a31-apb0-gates-clk", 109 .of_compatible = "allwinner,sun8i-a23-apb0-gates-clk", 110 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_gates_clk_res), 111 .resources = sun6i_a31_apb0_gates_clk_res, 112 }, 113 { 114 .name = "sun6i-a31-apb0-clock-reset", 115 .of_compatible = "allwinner,sun6i-a31-clock-reset", 116 .num_resources = ARRAY_SIZE(sun6i_a31_apb0_rstc_res), 117 .resources = sun6i_a31_apb0_rstc_res, 118 }, 119 { 120 .name = "sun8i-codec-analog", 121 .of_compatible = "allwinner,sun8i-a23-codec-analog", 122 .num_resources = ARRAY_SIZE(sun8i_codec_analog_res), 123 .resources = sun8i_codec_analog_res, 124 }, 125}; 126 127static const struct prcm_data sun6i_a31_prcm_data = { 128 .nsubdevs = ARRAY_SIZE(sun6i_a31_prcm_subdevs), 129 .subdevs = sun6i_a31_prcm_subdevs, 130}; 131 132static const struct prcm_data sun8i_a23_prcm_data = { 133 .nsubdevs = ARRAY_SIZE(sun8i_a23_prcm_subdevs), 134 .subdevs = sun8i_a23_prcm_subdevs, 135}; 136 137static const struct of_device_id sun6i_prcm_dt_ids[] = { 138 { 139 .compatible = "allwinner,sun6i-a31-prcm", 140 .data = &sun6i_a31_prcm_data, 141 }, 142 { 143 .compatible = "allwinner,sun8i-a23-prcm", 144 .data = &sun8i_a23_prcm_data, 145 }, 146 { /* sentinel */ }, 147}; 148 149static int sun6i_prcm_probe(struct platform_device *pdev) 150{ 151 struct device_node *np = pdev->dev.of_node; 152 const struct of_device_id *match; 153 const struct prcm_data *data; 154 struct resource *res; 155 int ret; 156 157 match = of_match_node(sun6i_prcm_dt_ids, np); 158 if (!match) 159 return -EINVAL; 160 161 data = match->data; 162 163 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 164 if (!res) { 165 dev_err(&pdev->dev, "no prcm memory region provided\n"); 166 return -ENOENT; 167 } 168 169 ret = mfd_add_devices(&pdev->dev, 0, data->subdevs, data->nsubdevs, 170 res, -1, NULL); 171 if (ret) { 172 dev_err(&pdev->dev, "failed to add subdevices\n"); 173 return ret; 174 } 175 176 return 0; 177} 178 179static struct platform_driver sun6i_prcm_driver = { 180 .driver = { 181 .name = "sun6i-prcm", 182 .of_match_table = sun6i_prcm_dt_ids, 183 }, 184 .probe = sun6i_prcm_probe, 185}; 186builtin_platform_driver(sun6i_prcm_driver);