Lines Matching +full:cs +full:- +full:to +full:- +full:clk
1 // SPDX-License-Identifier: GPL-2.0-only
5 * Copyright (C) 2010 - 2013 Texas Instruments Incorporated. http://www.ti.com/
8 * Murali Karicheri <m-karicheri2@ti.com>
12 #include <linux/clk.h>
20 #include <linux/platform_data/ti-aemif.h>
84 * struct aemif_cs_data: structure to hold cs parameters
85 * @cs: chip-select number
98 u8 cs; member
112 * struct aemif_device: structure to hold device data
114 * @clk: source clock
116 * @num_cs: number of assigned chip-selects
117 * @cs_offset: start number of cs nodes
118 * @cs_data: array of chip-select settings
122 struct clk *clk; member
130 * aemif_calc_rate - calculate timing data.
131 * @pdev: platform device to calculate for
133 * @clk: The input clock rate in kHz.
140 unsigned long clk, int max) in aemif_calc_rate() argument
144 result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1; in aemif_calc_rate()
146 dev_dbg(&pdev->dev, "%s: result %d from %ld, %d\n", __func__, result, in aemif_calc_rate()
147 clk, wanted); in aemif_calc_rate()
149 /* It is generally OK to have a more relaxed timing than requested... */ in aemif_calc_rate()
155 result = -EINVAL; in aemif_calc_rate()
161 * aemif_config_abus - configure async bus parameters
162 * @pdev: platform device to configure for
170 * chip-select.
177 struct aemif_cs_data *data = &aemif->cs_data[csnum]; in aemif_config_abus()
179 unsigned long clk_rate = aemif->clk_rate; in aemif_config_abus()
183 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; in aemif_config_abus()
185 ta = aemif_calc_rate(pdev, data->ta, clk_rate, TA_MAX); in aemif_config_abus()
186 rhold = aemif_calc_rate(pdev, data->rhold, clk_rate, RHOLD_MAX); in aemif_config_abus()
187 rstrobe = aemif_calc_rate(pdev, data->rstrobe, clk_rate, RSTROBE_MAX); in aemif_config_abus()
188 rsetup = aemif_calc_rate(pdev, data->rsetup, clk_rate, RSETUP_MAX); in aemif_config_abus()
189 whold = aemif_calc_rate(pdev, data->whold, clk_rate, WHOLD_MAX); in aemif_config_abus()
190 wstrobe = aemif_calc_rate(pdev, data->wstrobe, clk_rate, WSTROBE_MAX); in aemif_config_abus()
191 wsetup = aemif_calc_rate(pdev, data->wsetup, clk_rate, WSETUP_MAX); in aemif_config_abus()
195 dev_err(&pdev->dev, "%s: cannot get suitable timings\n", in aemif_config_abus()
197 return -EINVAL; in aemif_config_abus()
203 set |= (data->asize & ACR_ASIZE_MASK); in aemif_config_abus()
204 if (data->enable_ew) in aemif_config_abus()
206 if (data->enable_ss) in aemif_config_abus()
209 val = readl(aemif->base + offset); in aemif_config_abus()
212 writel(val, aemif->base + offset); in aemif_config_abus()
223 * aemif_get_hw_params - function to read hw register values
224 * @pdev: platform device to read for
229 * the case when driver needs to use defaults in hardware.
234 struct aemif_cs_data *data = &aemif->cs_data[csnum]; in aemif_get_hw_params()
235 unsigned long clk_rate = aemif->clk_rate; in aemif_get_hw_params()
238 offset = A1CR_OFFSET + (data->cs - aemif->cs_offset) * 4; in aemif_get_hw_params()
239 val = readl(aemif->base + offset); in aemif_get_hw_params()
241 data->ta = aemif_cycles_to_nsec(TA_VAL(val), clk_rate); in aemif_get_hw_params()
242 data->rhold = aemif_cycles_to_nsec(RHOLD_VAL(val), clk_rate); in aemif_get_hw_params()
243 data->rstrobe = aemif_cycles_to_nsec(RSTROBE_VAL(val), clk_rate); in aemif_get_hw_params()
244 data->rsetup = aemif_cycles_to_nsec(RSETUP_VAL(val), clk_rate); in aemif_get_hw_params()
245 data->whold = aemif_cycles_to_nsec(WHOLD_VAL(val), clk_rate); in aemif_get_hw_params()
246 data->wstrobe = aemif_cycles_to_nsec(WSTROBE_VAL(val), clk_rate); in aemif_get_hw_params()
247 data->wsetup = aemif_cycles_to_nsec(WSETUP_VAL(val), clk_rate); in aemif_get_hw_params()
248 data->enable_ew = EW_VAL(val); in aemif_get_hw_params()
249 data->enable_ss = SSTROBE_VAL(val); in aemif_get_hw_params()
250 data->asize = val & ASIZE_MAX; in aemif_get_hw_params()
254 * of_aemif_parse_abus_config - parse CS configuration from DT
255 * @pdev: platform device to parse for
259 * configured in a cs device binding node.
266 u32 cs; in of_aemif_parse_abus_config() local
269 if (of_property_read_u32(np, "ti,cs-chipselect", &cs)) { in of_aemif_parse_abus_config()
270 dev_dbg(&pdev->dev, "cs property is required"); in of_aemif_parse_abus_config()
271 return -EINVAL; in of_aemif_parse_abus_config()
274 if (cs - aemif->cs_offset >= NUM_CS || cs < aemif->cs_offset) { in of_aemif_parse_abus_config()
275 dev_dbg(&pdev->dev, "cs number is incorrect %d", cs); in of_aemif_parse_abus_config()
276 return -EINVAL; in of_aemif_parse_abus_config()
279 if (aemif->num_cs >= NUM_CS) { in of_aemif_parse_abus_config()
280 dev_dbg(&pdev->dev, "cs count is more than %d", NUM_CS); in of_aemif_parse_abus_config()
281 return -EINVAL; in of_aemif_parse_abus_config()
284 data = &aemif->cs_data[aemif->num_cs]; in of_aemif_parse_abus_config()
285 data->cs = cs; in of_aemif_parse_abus_config()
288 aemif_get_hw_params(pdev, aemif->num_cs++); in of_aemif_parse_abus_config()
291 if (!of_property_read_u32(np, "ti,cs-min-turnaround-ns", &val)) in of_aemif_parse_abus_config()
292 data->ta = val; in of_aemif_parse_abus_config()
294 if (!of_property_read_u32(np, "ti,cs-read-hold-ns", &val)) in of_aemif_parse_abus_config()
295 data->rhold = val; in of_aemif_parse_abus_config()
297 if (!of_property_read_u32(np, "ti,cs-read-strobe-ns", &val)) in of_aemif_parse_abus_config()
298 data->rstrobe = val; in of_aemif_parse_abus_config()
300 if (!of_property_read_u32(np, "ti,cs-read-setup-ns", &val)) in of_aemif_parse_abus_config()
301 data->rsetup = val; in of_aemif_parse_abus_config()
303 if (!of_property_read_u32(np, "ti,cs-write-hold-ns", &val)) in of_aemif_parse_abus_config()
304 data->whold = val; in of_aemif_parse_abus_config()
306 if (!of_property_read_u32(np, "ti,cs-write-strobe-ns", &val)) in of_aemif_parse_abus_config()
307 data->wstrobe = val; in of_aemif_parse_abus_config()
309 if (!of_property_read_u32(np, "ti,cs-write-setup-ns", &val)) in of_aemif_parse_abus_config()
310 data->wsetup = val; in of_aemif_parse_abus_config()
312 if (!of_property_read_u32(np, "ti,cs-bus-width", &val)) in of_aemif_parse_abus_config()
314 data->asize = 1; in of_aemif_parse_abus_config()
315 data->enable_ew = of_property_read_bool(np, "ti,cs-extended-wait-mode"); in of_aemif_parse_abus_config()
316 data->enable_ss = of_property_read_bool(np, "ti,cs-select-strobe-mode"); in of_aemif_parse_abus_config()
321 { .compatible = "ti,davinci-aemif", },
322 { .compatible = "ti,da850-aemif", },
330 int ret = -ENODEV; in aemif_probe()
331 struct device *dev = &pdev->dev; in aemif_probe()
332 struct device_node *np = dev->of_node; in aemif_probe()
340 return -ENOMEM; in aemif_probe()
342 pdata = dev_get_platdata(&pdev->dev); in aemif_probe()
343 dev_lookup = pdata ? pdata->dev_lookup : NULL; in aemif_probe()
347 aemif->clk = devm_clk_get(dev, NULL); in aemif_probe()
348 if (IS_ERR(aemif->clk)) { in aemif_probe()
350 return PTR_ERR(aemif->clk); in aemif_probe()
353 ret = clk_prepare_enable(aemif->clk); in aemif_probe()
357 aemif->clk_rate = clk_get_rate(aemif->clk) / MSEC_PER_SEC; in aemif_probe()
359 if (np && of_device_is_compatible(np, "ti,da850-aemif")) in aemif_probe()
360 aemif->cs_offset = 2; in aemif_probe()
362 aemif->cs_offset = pdata->cs_offset; in aemif_probe()
364 aemif->base = devm_platform_ioremap_resource(pdev, 0); in aemif_probe()
365 if (IS_ERR(aemif->base)) { in aemif_probe()
366 ret = PTR_ERR(aemif->base); in aemif_probe()
372 * For every controller device node, there is a cs device node in aemif_probe()
374 * functions iterate over these nodes and update the cs data in aemif_probe()
384 } else if (pdata && pdata->num_abus_data > 0) { in aemif_probe()
385 for (i = 0; i < pdata->num_abus_data; i++, aemif->num_cs++) { in aemif_probe()
386 aemif->cs_data[i].cs = pdata->abus_data[i].cs; in aemif_probe()
391 for (i = 0; i < aemif->num_cs; i++) { in aemif_probe()
395 aemif->cs_data[i].cs); in aemif_probe()
401 * Create a child devices explicitly from here to guarantee that the in aemif_probe()
414 for (i = 0; i < pdata->num_sub_devices; i++) { in aemif_probe()
415 pdata->sub_devices[i].dev.parent = dev; in aemif_probe()
416 ret = platform_device_register(&pdata->sub_devices[i]); in aemif_probe()
419 pdata->sub_devices[i].name); in aemif_probe()
426 clk_disable_unprepare(aemif->clk); in aemif_probe()
434 clk_disable_unprepare(aemif->clk); in aemif_remove()
442 .name = "ti-aemif",
449 MODULE_AUTHOR("Murali Karicheri <m-karicheri2@ti.com>");