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

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")

Tested-by: Carlo Caione <carlo@endlessm.com>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>

authored by

Pierre-Louis Bossart and committed by
Mauro Carvalho Chehab
d5426f4c abe51392

+52 -332
+1
drivers/staging/media/atomisp/Kconfig
··· 1 1 menuconfig INTEL_ATOMISP 2 2 bool "Enable support to Intel MIPI camera drivers" 3 3 depends on X86 && EFI && MEDIA_CONTROLLER && PCI && ACPI 4 + select COMMON_CLK 4 5 help 5 6 Enable support for the Intel ISP2 camera interfaces and MIPI 6 7 sensor drivers.
-1
drivers/staging/media/atomisp/platform/Makefile
··· 2 2 # Makefile for camera drivers. 3 3 # 4 4 5 - obj-$(CONFIG_INTEL_ATOMISP) += clock/ 6 5 obj-$(CONFIG_INTEL_ATOMISP) += intel-mid/
-6
drivers/staging/media/atomisp/platform/clock/Makefile
··· 1 - # 2 - # Makefile for clock devices. 3 - # 4 - 5 - obj-$(CONFIG_INTEL_ATOMISP) += vlv2_plat_clock.o 6 - obj-$(CONFIG_INTEL_ATOMISP) += platform_vlv2_plat_clk.o
-40
drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.c
··· 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 - 26 - static 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 - 40 - device_initcall(vlv2_plat_clk_init);
-26
drivers/staging/media/atomisp/platform/clock/platform_vlv2_plat_clk.h
··· 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 - 24 - extern void __init *vlv2_plat_clk_device_platform_data( 25 - void *info) __attribute__((weak)); 26 - #endif
-247
drivers/staging/media/atomisp/platform/clock/vlv2_plat_clock.c
··· 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 - 58 - static DEFINE_MUTEX(clk_mutex); 59 - static 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 - */ 66 - int 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 - } 94 - EXPORT_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 - */ 102 - int 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 - } 122 - EXPORT_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 - */ 132 - int 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 - } 160 - EXPORT_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 - */ 168 - int 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 - } 188 - EXPORT_SYMBOL_GPL(vlv2_plat_get_clock_status); 189 - 190 - static 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 - 208 - static const struct platform_device_id vlv2_plat_clk_id[] = { 209 - {"vlv2_plat_clk", 0}, 210 - {} 211 - }; 212 - 213 - static 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 - 224 - static int vlv2_suspend(struct device *device) 225 - { 226 - return 0; 227 - } 228 - 229 - static const struct dev_pm_ops vlv2_pm_ops = { 230 - .suspend = vlv2_suspend, 231 - .resume = vlv2_resume, 232 - }; 233 - 234 - static 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 - 243 - static int __init vlv2_plat_clk_init(void) 244 - { 245 - return platform_driver_register(&vlv2_plat_clk_driver); 246 - } 247 - arch_initcall(vlv2_plat_clk_init);
+51 -12
drivers/staging/media/atomisp/platform/intel-mid/atomisp_gmin_platform.c
··· 4 4 #include <linux/efi.h> 5 5 #include <linux/pci.h> 6 6 #include <linux/acpi.h> 7 + #include <linux/clk.h> 7 8 #include <linux/delay.h> 8 9 #include <media/v4l2-subdev.h> 9 10 #include <linux/mfd/intel_soc_pmic.h> 10 - #include "../../include/linux/vlv2_plat_clock.h" 11 11 #include <linux/regulator/consumer.h> 12 12 #include <linux/gpio/consumer.h> 13 13 #include <linux/gpio.h> ··· 17 17 18 18 #define MAX_SUBDEVS 8 19 19 20 - /* Should be defined in vlv2_plat_clock API, isn't: */ 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 20 + #define VLV2_CLK_PLL_19P2MHZ 1 /* XTAL on CHT */ 25 21 #define ELDO1_SEL_REG 0x19 26 22 #define ELDO1_1P8V 0x16 27 23 #define ELDO1_CTRL_SHIFT 0x00 ··· 29 33 struct v4l2_subdev *subdev; 30 34 int clock_num; 31 35 int clock_src; 36 + struct clk *pmc_clk; 32 37 struct gpio_desc *gpio0; 33 38 struct gpio_desc *gpio1; 34 39 struct regulator *v1p8_reg; ··· 341 344 return 0; 342 345 } 343 346 347 + #define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */ 348 + static char gmin_pmc_clk_name[GMIN_PMC_CLK_NAME]; 349 + 344 350 static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) 345 351 { 346 352 int i, ret; ··· 376 376 gmin_subdevs[i].csi_lanes = gmin_get_var_int(dev, "CsiLanes", 1); 377 377 gmin_subdevs[i].gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW); 378 378 gmin_subdevs[i].gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW); 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); 379 410 380 411 if (!IS_ERR(gmin_subdevs[i].gpio0)) { 381 412 ret = gpiod_direction_output(gmin_subdevs[i].gpio0, 0); ··· 570 539 { 571 540 int ret = 0; 572 541 struct gmin_subdev *gs = find_gmin_subdev(subdev); 542 + struct i2c_client *client = v4l2_get_subdevdata(subdev); 573 543 574 - if (on) 575 - ret = vlv2_plat_set_clock_freq(gs->clock_num, gs->clock_src); 576 - if (ret) 577 - return ret; 578 - return vlv2_plat_configure_clock(gs->clock_num, 579 - on ? VLV2_CLK_ON : VLV2_CLK_OFF); 544 + if (on) { 545 + ret = clk_set_rate(gs->pmc_clk, gs->clock_src); 546 + 547 + if (ret) 548 + dev_err(&client->dev, "unable to set PMC rate %d\n", 549 + gs->clock_src); 550 + 551 + ret = clk_prepare_enable(gs->pmc_clk); 552 + } else { 553 + clk_disable_unprepare(gs->pmc_clk); 554 + } 555 + 556 + return ret; 580 557 } 581 558 582 559 static int gmin_csi_cfg(struct v4l2_subdev *sd, int flag)