1/* 2 * Intel Quark MFD PCI driver for I2C & GPIO 3 * 4 * Copyright(c) 2014 Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 * Intel Quark PCI device for I2C and GPIO controller sharing the same 16 * PCI function. This PCI driver will split the 2 devices into their 17 * respective drivers. 18 */ 19 20#include <linux/kernel.h> 21#include <linux/module.h> 22#include <linux/pci.h> 23#include <linux/mfd/core.h> 24#include <linux/clkdev.h> 25#include <linux/clk-provider.h> 26#include <linux/dmi.h> 27#include <linux/platform_data/gpio-dwapb.h> 28#include <linux/platform_data/i2c-designware.h> 29 30/* PCI BAR for register base address */ 31#define MFD_I2C_BAR 0 32#define MFD_GPIO_BAR 1 33 34/* The base GPIO number under GPIOLIB framework */ 35#define INTEL_QUARK_MFD_GPIO_BASE 8 36 37/* The default number of South-Cluster GPIO on Quark. */ 38#define INTEL_QUARK_MFD_NGPIO 8 39 40/* The DesignWare GPIO ports on Quark. */ 41#define INTEL_QUARK_GPIO_NPORTS 1 42 43#define INTEL_QUARK_IORES_MEM 0 44#define INTEL_QUARK_IORES_IRQ 1 45 46#define INTEL_QUARK_I2C_CONTROLLER_CLK "i2c_designware.0" 47 48/* The Quark I2C controller source clock */ 49#define INTEL_QUARK_I2C_CLK_HZ 33000000 50 51#define INTEL_QUARK_I2C_NCLK 1 52 53struct intel_quark_mfd { 54 struct pci_dev *pdev; 55 struct clk *i2c_clk; 56 struct clk_lookup *i2c_clk_lookup; 57}; 58 59struct i2c_mode_info { 60 const char *name; 61 unsigned int i2c_scl_freq; 62}; 63 64static const struct i2c_mode_info platform_i2c_mode_info[] = { 65 { 66 .name = "Galileo", 67 .i2c_scl_freq = 100000, 68 }, 69 { 70 .name = "GalileoGen2", 71 .i2c_scl_freq = 400000, 72 }, 73 {} 74}; 75 76static struct resource intel_quark_i2c_res[] = { 77 [INTEL_QUARK_IORES_MEM] = { 78 .flags = IORESOURCE_MEM, 79 }, 80 [INTEL_QUARK_IORES_IRQ] = { 81 .flags = IORESOURCE_IRQ, 82 }, 83}; 84 85static struct resource intel_quark_gpio_res[] = { 86 [INTEL_QUARK_IORES_MEM] = { 87 .flags = IORESOURCE_MEM, 88 }, 89}; 90 91static struct mfd_cell intel_quark_mfd_cells[] = { 92 { 93 .id = MFD_GPIO_BAR, 94 .name = "gpio-dwapb", 95 .num_resources = ARRAY_SIZE(intel_quark_gpio_res), 96 .resources = intel_quark_gpio_res, 97 .ignore_resource_conflicts = true, 98 }, 99 { 100 .id = MFD_I2C_BAR, 101 .name = "i2c_designware", 102 .num_resources = ARRAY_SIZE(intel_quark_i2c_res), 103 .resources = intel_quark_i2c_res, 104 .ignore_resource_conflicts = true, 105 }, 106}; 107 108static const struct pci_device_id intel_quark_mfd_ids[] = { 109 { PCI_VDEVICE(INTEL, 0x0934), }, 110 {}, 111}; 112MODULE_DEVICE_TABLE(pci, intel_quark_mfd_ids); 113 114static int intel_quark_register_i2c_clk(struct intel_quark_mfd *quark_mfd) 115{ 116 struct pci_dev *pdev = quark_mfd->pdev; 117 struct clk_lookup *i2c_clk_lookup; 118 struct clk *i2c_clk; 119 int ret; 120 121 i2c_clk_lookup = devm_kcalloc(&pdev->dev, INTEL_QUARK_I2C_NCLK, 122 sizeof(*i2c_clk_lookup), GFP_KERNEL); 123 if (!i2c_clk_lookup) 124 return -ENOMEM; 125 126 i2c_clk_lookup[0].dev_id = INTEL_QUARK_I2C_CONTROLLER_CLK; 127 128 i2c_clk = clk_register_fixed_rate(&pdev->dev, 129 INTEL_QUARK_I2C_CONTROLLER_CLK, NULL, 130 CLK_IS_ROOT, INTEL_QUARK_I2C_CLK_HZ); 131 132 quark_mfd->i2c_clk_lookup = i2c_clk_lookup; 133 quark_mfd->i2c_clk = i2c_clk; 134 135 ret = clk_register_clkdevs(i2c_clk, i2c_clk_lookup, 136 INTEL_QUARK_I2C_NCLK); 137 if (ret) 138 dev_err(&pdev->dev, "Fixed clk register failed: %d\n", ret); 139 140 return ret; 141} 142 143static void intel_quark_unregister_i2c_clk(struct pci_dev *pdev) 144{ 145 struct intel_quark_mfd *quark_mfd = dev_get_drvdata(&pdev->dev); 146 147 if (!quark_mfd->i2c_clk || !quark_mfd->i2c_clk_lookup) 148 return; 149 150 clkdev_drop(quark_mfd->i2c_clk_lookup); 151 clk_unregister(quark_mfd->i2c_clk); 152} 153 154static int intel_quark_i2c_setup(struct pci_dev *pdev, struct mfd_cell *cell) 155{ 156 const char *board_name = dmi_get_system_info(DMI_BOARD_NAME); 157 const struct i2c_mode_info *info; 158 struct dw_i2c_platform_data *pdata; 159 struct resource *res = (struct resource *)cell->resources; 160 struct device *dev = &pdev->dev; 161 162 res[INTEL_QUARK_IORES_MEM].start = 163 pci_resource_start(pdev, MFD_I2C_BAR); 164 res[INTEL_QUARK_IORES_MEM].end = 165 pci_resource_end(pdev, MFD_I2C_BAR); 166 167 res[INTEL_QUARK_IORES_IRQ].start = pdev->irq; 168 res[INTEL_QUARK_IORES_IRQ].end = pdev->irq; 169 170 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 171 if (!pdata) 172 return -ENOMEM; 173 174 /* Normal mode by default */ 175 pdata->i2c_scl_freq = 100000; 176 177 if (board_name) { 178 for (info = platform_i2c_mode_info; info->name; info++) { 179 if (!strcmp(board_name, info->name)) { 180 pdata->i2c_scl_freq = info->i2c_scl_freq; 181 break; 182 } 183 } 184 } 185 186 cell->platform_data = pdata; 187 cell->pdata_size = sizeof(*pdata); 188 189 return 0; 190} 191 192static int intel_quark_gpio_setup(struct pci_dev *pdev, struct mfd_cell *cell) 193{ 194 struct dwapb_platform_data *pdata; 195 struct resource *res = (struct resource *)cell->resources; 196 struct device *dev = &pdev->dev; 197 198 res[INTEL_QUARK_IORES_MEM].start = 199 pci_resource_start(pdev, MFD_GPIO_BAR); 200 res[INTEL_QUARK_IORES_MEM].end = 201 pci_resource_end(pdev, MFD_GPIO_BAR); 202 203 pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); 204 if (!pdata) 205 return -ENOMEM; 206 207 /* For intel quark x1000, it has only one port: portA */ 208 pdata->nports = INTEL_QUARK_GPIO_NPORTS; 209 pdata->properties = devm_kcalloc(dev, pdata->nports, 210 sizeof(*pdata->properties), 211 GFP_KERNEL); 212 if (!pdata->properties) 213 return -ENOMEM; 214 215 /* Set the properties for portA */ 216 pdata->properties->node = NULL; 217 pdata->properties->name = "intel-quark-x1000-gpio-portA"; 218 pdata->properties->idx = 0; 219 pdata->properties->ngpio = INTEL_QUARK_MFD_NGPIO; 220 pdata->properties->gpio_base = INTEL_QUARK_MFD_GPIO_BASE; 221 pdata->properties->irq = pdev->irq; 222 pdata->properties->irq_shared = true; 223 224 cell->platform_data = pdata; 225 cell->pdata_size = sizeof(*pdata); 226 227 return 0; 228} 229 230static int intel_quark_mfd_probe(struct pci_dev *pdev, 231 const struct pci_device_id *id) 232{ 233 struct intel_quark_mfd *quark_mfd; 234 int ret; 235 236 ret = pcim_enable_device(pdev); 237 if (ret) 238 return ret; 239 240 quark_mfd = devm_kzalloc(&pdev->dev, sizeof(*quark_mfd), GFP_KERNEL); 241 if (!quark_mfd) 242 return -ENOMEM; 243 quark_mfd->pdev = pdev; 244 245 ret = intel_quark_register_i2c_clk(quark_mfd); 246 if (ret) 247 return ret; 248 249 dev_set_drvdata(&pdev->dev, quark_mfd); 250 251 ret = intel_quark_i2c_setup(pdev, &intel_quark_mfd_cells[1]); 252 if (ret) 253 return ret; 254 255 ret = intel_quark_gpio_setup(pdev, &intel_quark_mfd_cells[0]); 256 if (ret) 257 return ret; 258 259 return mfd_add_devices(&pdev->dev, 0, intel_quark_mfd_cells, 260 ARRAY_SIZE(intel_quark_mfd_cells), NULL, 0, 261 NULL); 262} 263 264static void intel_quark_mfd_remove(struct pci_dev *pdev) 265{ 266 intel_quark_unregister_i2c_clk(pdev); 267 mfd_remove_devices(&pdev->dev); 268} 269 270static struct pci_driver intel_quark_mfd_driver = { 271 .name = "intel_quark_mfd_i2c_gpio", 272 .id_table = intel_quark_mfd_ids, 273 .probe = intel_quark_mfd_probe, 274 .remove = intel_quark_mfd_remove, 275}; 276 277module_pci_driver(intel_quark_mfd_driver); 278 279MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>"); 280MODULE_DESCRIPTION("Intel Quark MFD PCI driver for I2C & GPIO"); 281MODULE_LICENSE("GPL v2"); 282