History

media: staging: atomisp: use clock framework for camera clocks

The Atom ISP driver initializes and configures PMC clocks which are already handled by the clock framework. Remove all legacy vlv2_platform_clock stuff and move to the clk API to avoid conflicts, e.g. with audio machine drivers enabling the MCLK for external codecs Fixes: a49d25364dfb ("staging/atomisp: Add support for the Intel IPU v2")

Pierre-Louis Bossart committed 9 years ago

Commit d5426f41 parent abe51397 files · +52 −332Browse files

Unified · Split

7 files
  1. drivers/staging/media/atomisp/Kconfig +1 −0
  2. drivers/staging/media/atomisp/platform/Makefile +0 −1
  3. drivers/staging/media/atomisp/platform/clock/Makefile +0 −6
  4. drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.c +0 −40
  5. drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.h +0 −26
  6. drivers/staging/media/atomisp/platform/clock/vlv2_plat_clock.c +0 −247
  7. drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c +51 −12
drivers/staging/media/atomisp/Kconfig+1−0
@@ -1,6 +1,7 @@
1menuconfig INTEL_ATOMISP1menuconfig INTEL_ATOMISP
2 bool "Enable support to Intel MIPI camera drivers"2 bool "Enable support to Intel MIPI camera drivers"
3 depends on X86 && EFI && MEDIA_CONTROLLER && PCI && ACPI3 depends on X86 && EFI && MEDIA_CONTROLLER && PCI && ACPI
4 select COMMON_CLK
4 help5 help
5 Enable support for the Intel ISP2 camera interfaces and MIPI6 Enable support for the Intel ISP2 camera interfaces and MIPI
6 sensor drivers.7 sensor drivers.
drivers/staging/media/atomisp/platform/Makefile+0−1
@@ -2,5 +2,4 @@ · 1 unmodified line
2# Makefile for camera drivers.2# Makefile for camera drivers.
3#3#
4 4
5obj-$(CONFIG_INTEL_ATOMISP) += clock/
6obj-$(CONFIG_INTEL_ATOMISP) += intel-mid/5obj-$(CONFIG_INTEL_ATOMISP) += intel-mid/
drivers/staging/media/atomisp/platform/clock/Makefile+0−6
@@ -1,6 +0,0 @@
1#
2# Makefile for clock devices.
3#
4
5obj-$(CONFIG_INTEL_ATOMISP) += vlv2_plat_clock.o
6obj-$(CONFIG_INTEL_ATOMISP) += platform_vlv2_plat_clk.o
drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.c+0−40
@@ -1,40 +0,0 @@
1/*
2 * platform_vlv2_plat_clk.c - VLV2 platform clock driver
3 * Copyright (C) 2013 Intel Corporation
4 *
5 * Author: Asutosh Pathak <asutosh.pathak@intel.com>
6 * Author: Chandra Sekhar Anagani <chandra.sekhar.anagani@intel.com>
7 * Author: Sergio Aguirre <sergio.a.aguirre.rodriguez@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19
20#include <linux/device.h>
21#include <linux/err.h>
22#include <linux/module.h>
23#include <linux/platform_device.h>
24#include <linux/printk.h>
25
26static int __init vlv2_plat_clk_init(void)
27{
28 struct platform_device *pdev;
29
30 pdev = platform_device_register_simple("vlv2_plat_clk", -1, NULL, 0);
31 if (IS_ERR(pdev)) {
32 pr_err("platform_vlv2_plat_clk:register failed: %ld\n",
33 PTR_ERR(pdev));
34 return PTR_ERR(pdev);
35 }
36
37 return 0;
38}
39
40device_initcall(vlv2_plat_clk_init);
drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.h+0−26
@@ -1,26 +0,0 @@
1/*
2 * platform_vlv2_plat_clk.h: platform clock driver library header file
3 * Copyright (C) 2013 Intel Corporation
4 *
5 * Author: Asutosh Pathak <asutosh.pathak@intel.com>
6 * Author: Chandra Sekhar Anagani <chandra.sekhar.anagani@intel.com>
7 * Author: Sergio Aguirre <sergio.a.aguirre.rodriguez@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 */
19#ifndef _PLATFORM_VLV2_PLAT_CLK_H_
20#define _PLATFORM_VLV2_PLAT_CLK_H_
21
22#include <linux/sfi.h>
23
24extern void __init *vlv2_plat_clk_device_platform_data(
25 void *info) __attribute__((weak));
26#endif
drivers/staging/media/atomisp/platform/clock/vlv2_plat_clock.c+0−247
@@ -1,247 +0,0 @@
1/*
2 * vlv2_plat_clock.c - VLV2 platform clock driver
3 * Copyright (C) 2013 Intel Corporation
4 *
5 * Author: Asutosh Pathak <asutosh.pathak@intel.com>
6 * Author: Chandra Sekhar Anagani <chandra.sekhar.anagani@intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
20 */
21
22#include <linux/err.h>
23#include <linux/io.h>
24#include <linux/init.h>
25#include <linux/platform_device.h>
26#include "../../include/linux/vlv2_plat_clock.h"
27
28/* NOTE: Most of below constants could come from platform data.
29 * To be fixed when appropriate ACPI support comes.
30 */
31#define VLV2_PMC_CLK_BASE_ADDRESS 0xfed03060
32#define PLT_CLK_CTL_OFFSET(x) (0x04 * (x))
33
34#define CLK_CONFG_BIT_POS 0
35#define CLK_CONFG_BIT_LEN 2
36#define CLK_CONFG_D3_GATED 0
37#define CLK_CONFG_FORCE_ON 1
38#define CLK_CONFG_FORCE_OFF 2
39
40#define CLK_FREQ_TYPE_BIT_POS 2
41#define CLK_FREQ_TYPE_BIT_LEN 1
42#define CLK_FREQ_TYPE_XTAL 0 /* 25 MHz */
43#define CLK_FREQ_TYPE_PLL 1 /* 19.2 MHz */
44
45#define MAX_CLK_COUNT 5
46
47/* Helper macros to manipulate bitfields */
48#define REG_MASK(n) (((1 << (n##_BIT_LEN)) - 1) << (n##_BIT_POS))
49#define REG_SET_FIELD(r, n, v) (((r) & ~REG_MASK(n)) | \
50 (((v) << (n##_BIT_POS)) & REG_MASK(n)))
51#define REG_GET_FIELD(r, n) (((r) & REG_MASK(n)) >> n##_BIT_POS)
52/*
53 * vlv2 platform has 6 platform clocks, controlled by 4 byte registers
54 * Total size required for mapping is 6*4 = 24 bytes
55 */
56#define PMC_MAP_SIZE 24
57
58static DEFINE_MUTEX(clk_mutex);
59static void __iomem *pmc_base;
60
61/*
62 * vlv2_plat_set_clock_freq - Set clock frequency to a specified platform clock
63 * @clk_num: Platform clock number (i.e. 0, 1, 2, ...,5)
64 * @freq_type: Clock frequency (0-25 MHz(XTAL), 1-19.2 MHz(PLL) )
65 */
66int vlv2_plat_set_clock_freq(int clk_num, int freq_type)
67{
68 void __iomem *addr;
69
70 if (clk_num < 0 || clk_num >= MAX_CLK_COUNT) {
71 pr_err("Clock number out of range (%d)\n", clk_num);
72 return -EINVAL;
73 }
74
75 if (freq_type != CLK_FREQ_TYPE_XTAL &&
76 freq_type != CLK_FREQ_TYPE_PLL) {
77 pr_err("wrong clock type\n");
78 return -EINVAL;
79 }
80
81 if (!pmc_base) {
82 pr_err("memio map is not set\n");
83 return -EINVAL;
84 }
85
86 addr = pmc_base + PLT_CLK_CTL_OFFSET(clk_num);
87
88 mutex_lock(&clk_mutex);
89 writel(REG_SET_FIELD(readl(addr), CLK_FREQ_TYPE, freq_type), addr);
90 mutex_unlock(&clk_mutex);
91
92 return 0;
93}
94EXPORT_SYMBOL_GPL(vlv2_plat_set_clock_freq);
95
96/*
97 * vlv2_plat_get_clock_freq - Get the status of specified platform clock
98 * @clk_num: Platform clock number (i.e. 0, 1, 2, ...,5)
99 *
100 * Returns 0 for 25 MHz(XTAL) and 1 for 19.2 MHz(PLL)
101 */
102int vlv2_plat_get_clock_freq(int clk_num)
103{
104 u32 ret;
105
106 if (clk_num < 0 || clk_num >= MAX_CLK_COUNT) {
107 pr_err("Clock number out of range (%d)\n", clk_num);
108 return -EINVAL;
109 }
110
111 if (!pmc_base) {
112 pr_err("memio map is not set\n");
113 return -EINVAL;
114 }
115
116 mutex_lock(&clk_mutex);
117 ret = REG_GET_FIELD(readl(pmc_base + PLT_CLK_CTL_OFFSET(clk_num)),
118 CLK_FREQ_TYPE);
119 mutex_unlock(&clk_mutex);
120 return ret;
121}
122EXPORT_SYMBOL_GPL(vlv2_plat_get_clock_freq);
123
124/*
125 * vlv2_plat_configure_clock - Configure the specified platform clock
126 * @clk_num: Platform clock number (i.e. 0, 1, 2, ...,5)
127 * @conf: Clock gating:
128 * 0 - Clock gated on D3 state
129 * 1 - Force on
130 * 2,3 - Force off
131 */
132int vlv2_plat_configure_clock(int clk_num, u32 conf)
133{
134 void __iomem *addr;
135
136 if (clk_num < 0 || clk_num >= MAX_CLK_COUNT) {
137 pr_err("Clock number out of range (%d)\n", clk_num);
138 return -EINVAL;
139 }
140
141 if (conf != CLK_CONFG_D3_GATED &&
142 conf != CLK_CONFG_FORCE_ON &&
143 conf != CLK_CONFG_FORCE_OFF) {
144 pr_err("Invalid clock configuration requested\n");
145 return -EINVAL;
146 }
147
148 if (!pmc_base) {
149 pr_err("memio map is not set\n");
150 return -EINVAL;
151 }
152
153 addr = pmc_base + PLT_CLK_CTL_OFFSET(clk_num);
154
155 mutex_lock(&clk_mutex);
156 writel(REG_SET_FIELD(readl(addr), CLK_CONFG, conf), addr);
157 mutex_unlock(&clk_mutex);
158 return 0;
159}
160EXPORT_SYMBOL_GPL(vlv2_plat_configure_clock);
161
162/*
163 * vlv2_plat_get_clock_status - Get the status of specified platform clock
164 * @clk_num: Platform clock number (i.e. 0, 1, 2, ...,5)
165 *
166 * Returns 1 - On, 0 - Off
167 */
168int vlv2_plat_get_clock_status(int clk_num)
169{
170 int ret;
171
172 if (clk_num < 0 || clk_num >= MAX_CLK_COUNT) {
173 pr_err("Clock number out of range (%d)\n", clk_num);
174 return -EINVAL;
175 }
176
177 if (!pmc_base) {
178 pr_err("memio map is not set\n");
179 return -EINVAL;
180 }
181
182 mutex_lock(&clk_mutex);
183 ret = (int)REG_GET_FIELD(readl(pmc_base + PLT_CLK_CTL_OFFSET(clk_num)),
184 CLK_CONFG);
185 mutex_unlock(&clk_mutex);
186 return ret;
187}
188EXPORT_SYMBOL_GPL(vlv2_plat_get_clock_status);
189
190static int vlv2_plat_clk_probe(struct platform_device *pdev)
191{
192 int i = 0;
193
194 pmc_base = ioremap_nocache(VLV2_PMC_CLK_BASE_ADDRESS, PMC_MAP_SIZE);
195 if (!pmc_base) {
196 dev_err(&pdev->dev, "I/O memory remapping failed\n");
197 return -ENOMEM;
198 }
199
200 /* Initialize all clocks as disabled */
201 for (i = 0; i < MAX_CLK_COUNT; i++)
202 vlv2_plat_configure_clock(i, CLK_CONFG_FORCE_OFF);
203
204 dev_info(&pdev->dev, "vlv2_plat_clk initialized\n");
205 return 0;
206}
207
208static const struct platform_device_id vlv2_plat_clk_id[] = {
209 {"vlv2_plat_clk", 0},
210 {}
211};
212
213static int vlv2_resume(struct device *device)
214{
215 int i;
216
217 /* Initialize all clocks as disabled */
218 for (i = 0; i < MAX_CLK_COUNT; i++)
219 vlv2_plat_configure_clock(i, CLK_CONFG_FORCE_OFF);
220
221 return 0;
222}
223
224static int vlv2_suspend(struct device *device)
225{
226 return 0;
227}
228
229static const struct dev_pm_ops vlv2_pm_ops = {
230 .suspend = vlv2_suspend,
231 .resume = vlv2_resume,
232};
233
234static struct platform_driver vlv2_plat_clk_driver = {
235 .probe = vlv2_plat_clk_probe,
236 .id_table = vlv2_plat_clk_id,
237 .driver = {
238 .name = "vlv2_plat_clk",
239 .pm = &vlv2_pm_ops,
240 },
241};
242
243static int __init vlv2_plat_clk_init(void)
244{
245 return platform_driver_register(&vlv2_plat_clk_driver);
246}
247arch_initcall(vlv2_plat_clk_init);
drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c+51−12
@@ -4,10 +4,10 @@ · 3 unmodified lines
4#include <linux/efi.h>4#include <linux/efi.h>
5#include <linux/pci.h>5#include <linux/pci.h>
6#include <linux/acpi.h>6#include <linux/acpi.h>
7#include <linux/clk.h>
7#include <linux/delay.h>8#include <linux/delay.h>
8#include <media/v4l2-subdev.h>9#include <media/v4l2-subdev.h>
9#include <linux/mfd/intel_soc_pmic.h>10#include <linux/mfd/intel_soc_pmic.h>
10#include "../../include/linux/vlv2_plat_clock.h"
11#include <linux/regulator/consumer.h>11#include <linux/regulator/consumer.h>
12#include <linux/gpio/consumer.h>12#include <linux/gpio/consumer.h>
13#include <linux/gpio.h>13#include <linux/gpio.h>
@@ -17,11 +17,7 @@ · 3 unmodified lines
17 17
18#define MAX_SUBDEVS 818#define MAX_SUBDEVS 8
19 19
20/* Should be defined in vlv2_plat_clock API, isn't: */20#define VLV2_CLK_PLL_19P2MHZ 1 /* XTAL on CHT */
21#define VLV2_CLK_PLL_19P2MHZ 1
22#define VLV2_CLK_XTAL_19P2MHZ 0
23#define VLV2_CLK_ON 1
24#define VLV2_CLK_OFF 2
25#define ELDO1_SEL_REG 0x1921#define ELDO1_SEL_REG 0x19
26#define ELDO1_1P8V 0x1622#define ELDO1_1P8V 0x16
27#define ELDO1_CTRL_SHIFT 0x0023#define ELDO1_CTRL_SHIFT 0x00
@@ -33,6 +29,7 @@ struct gmin_subdev { · 5 unmodified lines
33 struct v4l2_subdev *subdev;29 struct v4l2_subdev *subdev;
34 int clock_num;30 int clock_num;
35 int clock_src;31 int clock_src;
32 struct clk *pmc_clk;
36 struct gpio_desc *gpio0;33 struct gpio_desc *gpio0;
37 struct gpio_desc *gpio1;34 struct gpio_desc *gpio1;
38 struct regulator *v1p8_reg;35 struct regulator *v1p8_reg;
@@ -344,6 +341,9 @@ static int gmin_platform_deinit(void) · 305 unmodified lines
344 return 0;341 return 0;
345}342}
346 343
344#define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */
345static char gmin_pmc_clk_name[GMIN_PMC_CLK_NAME];
346
347static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)347static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev)
348{348{
349 int i, ret;349 int i, ret;
@@ -377,6 +377,37 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) · 27 unmodified lines
377 gmin_subdevs[i].gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW);377 gmin_subdevs[i].gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW);
378 gmin_subdevs[i].gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW);378 gmin_subdevs[i].gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW);
379 379
380 /* get PMC clock with clock framework */
381 snprintf(gmin_pmc_clk_name,
382 sizeof(gmin_pmc_clk_name),
383 "%s_%d", "pmc_plt_clk", gmin_subdevs[i].clock_num);
384
385 gmin_subdevs[i].pmc_clk = devm_clk_get(dev, gmin_pmc_clk_name);
386 if (IS_ERR(gmin_subdevs[i].pmc_clk)) {
387 ret = PTR_ERR(gmin_subdevs[i].pmc_clk);
388
389 dev_err(dev,
390 "Failed to get clk from %s : %d\n",
391 gmin_pmc_clk_name,
392 ret);
393
394 return NULL;
395 }
396
397 /*
398 * The firmware might enable the clock at
399 * boot (this information may or may not
400 * be reflected in the enable clock register).
401 * To change the rate we must disable the clock
402 * first to cover these cases. Due to common
403 * clock framework restrictions that do not allow
404 * to disable a clock that has not been enabled,
405 * we need to enable the clock first.
406 */
407 ret = clk_prepare_enable(gmin_subdevs[i].pmc_clk);
408 if (!ret)
409 clk_disable_unprepare(gmin_subdevs[i].pmc_clk);
410
380 if (!IS_ERR(gmin_subdevs[i].gpio0)) {411 if (!IS_ERR(gmin_subdevs[i].gpio0)) {
381 ret = gpiod_direction_output(gmin_subdevs[i].gpio0, 0);412 ret = gpiod_direction_output(gmin_subdevs[i].gpio0, 0);
382 if (ret)413 if (ret)
@@ -539,13 +570,21 @@ static int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on) · 156 unmodified lines
539{570{
540 int ret = 0;571 int ret = 0;
541 struct gmin_subdev *gs = find_gmin_subdev(subdev);572 struct gmin_subdev *gs = find_gmin_subdev(subdev);
573 struct i2c_client *client = v4l2_get_subdevdata(subdev);
574
575 if (on) {
576 ret = clk_set_rate(gs->pmc_clk, gs->clock_src);
577
578 if (ret)
579 dev_err(&client->dev, "unable to set PMC rate %d\n",
580 gs->clock_src);
542 581
543 if (on)582 ret = clk_prepare_enable(gs->pmc_clk);
544 ret = vlv2_plat_set_clock_freq(gs->clock_num, gs->clock_src);583 } else {
545 if (ret)584 clk_disable_unprepare(gs->pmc_clk);
546 return ret;585 }
547 return vlv2_plat_configure_clock(gs->clock_num,586
548 on ? VLV2_CLK_ON : VLV2_CLK_OFF);587 return ret;
549}588}
550 589
551static int gmin_csi_cfg(struct v4l2_subdev *sd, int flag)590static int gmin_csi_cfg(struct v4l2_subdev *sd, int flag)