root/drivers/mfd/intel_msic.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. intel_msic_reg_read
  2. intel_msic_reg_write
  3. intel_msic_reg_update
  4. intel_msic_bulk_read
  5. intel_msic_bulk_write
  6. intel_msic_irq_read
  7. intel_msic_init_devices
  8. intel_msic_remove_devices
  9. intel_msic_probe
  10. intel_msic_remove

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * Driver for Intel MSIC
   4  *
   5  * Copyright (C) 2011, Intel Corporation
   6  * Author: Mika Westerberg <mika.westerberg@linux.intel.com>
   7  */
   8 
   9 #include <linux/err.h>
  10 #include <linux/gpio.h>
  11 #include <linux/io.h>
  12 #include <linux/init.h>
  13 #include <linux/mfd/core.h>
  14 #include <linux/mfd/intel_msic.h>
  15 #include <linux/platform_device.h>
  16 #include <linux/slab.h>
  17 
  18 #include <asm/intel_scu_ipc.h>
  19 
  20 #define MSIC_VENDOR(id)         ((id >> 6) & 3)
  21 #define MSIC_VERSION(id)        (id & 0x3f)
  22 #define MSIC_MAJOR(id)          ('A' + ((id >> 3) & 7))
  23 #define MSIC_MINOR(id)          (id & 7)
  24 
  25 /*
  26  * MSIC interrupt tree is readable from SRAM at INTEL_MSIC_IRQ_PHYS_BASE.
  27  * Since IRQ block starts from address 0x002 we need to subtract that from
  28  * the actual IRQ status register address.
  29  */
  30 #define MSIC_IRQ_STATUS(x)      (INTEL_MSIC_IRQ_PHYS_BASE + ((x) - 2))
  31 #define MSIC_IRQ_STATUS_ACCDET  MSIC_IRQ_STATUS(INTEL_MSIC_ACCDET)
  32 
  33 /*
  34  * The SCU hardware has limitation of 16 bytes per read/write buffer on
  35  * Medfield.
  36  */
  37 #define SCU_IPC_RWBUF_LIMIT     16
  38 
  39 /**
  40  * struct intel_msic - an MSIC MFD instance
  41  * @pdev: pointer to the platform device
  42  * @vendor: vendor ID
  43  * @version: chip version
  44  * @irq_base: base address of the mapped MSIC SRAM interrupt tree
  45  */
  46 struct intel_msic {
  47         struct platform_device          *pdev;
  48         unsigned                        vendor;
  49         unsigned                        version;
  50         void __iomem                    *irq_base;
  51 };
  52 
  53 static struct resource msic_touch_resources[] = {
  54         DEFINE_RES_IRQ(0),
  55 };
  56 
  57 static struct resource msic_adc_resources[] = {
  58         DEFINE_RES_IRQ(0),
  59 };
  60 
  61 static struct resource msic_battery_resources[] = {
  62         DEFINE_RES_IRQ(0),
  63 };
  64 
  65 static struct resource msic_gpio_resources[] = {
  66         DEFINE_RES_IRQ(0),
  67 };
  68 
  69 static struct resource msic_audio_resources[] = {
  70         DEFINE_RES_IRQ_NAMED(0, "IRQ"),
  71         /*
  72          * We will pass IRQ_BASE to the driver now but this can be removed
  73          * when/if the driver starts to use intel_msic_irq_read().
  74          */
  75         DEFINE_RES_MEM_NAMED(MSIC_IRQ_STATUS_ACCDET, 1, "IRQ_BASE"),
  76 };
  77 
  78 static struct resource msic_hdmi_resources[] = {
  79         DEFINE_RES_IRQ(0),
  80 };
  81 
  82 static struct resource msic_thermal_resources[] = {
  83         DEFINE_RES_IRQ(0),
  84 };
  85 
  86 static struct resource msic_power_btn_resources[] = {
  87         DEFINE_RES_IRQ(0),
  88 };
  89 
  90 static struct resource msic_ocd_resources[] = {
  91         DEFINE_RES_IRQ(0),
  92 };
  93 
  94 /*
  95  * Devices that are part of the MSIC and are available via firmware
  96  * populated SFI DEVS table.
  97  */
  98 static struct mfd_cell msic_devs[] = {
  99         [INTEL_MSIC_BLOCK_TOUCH]        = {
 100                 .name                   = "msic_touch",
 101                 .num_resources          = ARRAY_SIZE(msic_touch_resources),
 102                 .resources              = msic_touch_resources,
 103         },
 104         [INTEL_MSIC_BLOCK_ADC]          = {
 105                 .name                   = "msic_adc",
 106                 .num_resources          = ARRAY_SIZE(msic_adc_resources),
 107                 .resources              = msic_adc_resources,
 108         },
 109         [INTEL_MSIC_BLOCK_BATTERY]      = {
 110                 .name                   = "msic_battery",
 111                 .num_resources          = ARRAY_SIZE(msic_battery_resources),
 112                 .resources              = msic_battery_resources,
 113         },
 114         [INTEL_MSIC_BLOCK_GPIO]         = {
 115                 .name                   = "msic_gpio",
 116                 .num_resources          = ARRAY_SIZE(msic_gpio_resources),
 117                 .resources              = msic_gpio_resources,
 118         },
 119         [INTEL_MSIC_BLOCK_AUDIO]        = {
 120                 .name                   = "msic_audio",
 121                 .num_resources          = ARRAY_SIZE(msic_audio_resources),
 122                 .resources              = msic_audio_resources,
 123         },
 124         [INTEL_MSIC_BLOCK_HDMI]         = {
 125                 .name                   = "msic_hdmi",
 126                 .num_resources          = ARRAY_SIZE(msic_hdmi_resources),
 127                 .resources              = msic_hdmi_resources,
 128         },
 129         [INTEL_MSIC_BLOCK_THERMAL]      = {
 130                 .name                   = "msic_thermal",
 131                 .num_resources          = ARRAY_SIZE(msic_thermal_resources),
 132                 .resources              = msic_thermal_resources,
 133         },
 134         [INTEL_MSIC_BLOCK_POWER_BTN]    = {
 135                 .name                   = "msic_power_btn",
 136                 .num_resources          = ARRAY_SIZE(msic_power_btn_resources),
 137                 .resources              = msic_power_btn_resources,
 138         },
 139         [INTEL_MSIC_BLOCK_OCD]          = {
 140                 .name                   = "msic_ocd",
 141                 .num_resources          = ARRAY_SIZE(msic_ocd_resources),
 142                 .resources              = msic_ocd_resources,
 143         },
 144 };
 145 
 146 /*
 147  * Other MSIC related devices which are not directly available via SFI DEVS
 148  * table. These can be pseudo devices, regulators etc. which are needed for
 149  * different purposes.
 150  *
 151  * These devices appear only after the MSIC driver itself is initialized so
 152  * we can guarantee that the SCU IPC interface is ready.
 153  */
 154 static const struct mfd_cell msic_other_devs[] = {
 155         /* Audio codec in the MSIC */
 156         {
 157                 .id                     = -1,
 158                 .name                   = "sn95031",
 159         },
 160 };
 161 
 162 /**
 163  * intel_msic_reg_read - read a single MSIC register
 164  * @reg: register to read
 165  * @val: register value is placed here
 166  *
 167  * Read a single register from MSIC. Returns %0 on success and negative
 168  * errno in case of failure.
 169  *
 170  * Function may sleep.
 171  */
 172 int intel_msic_reg_read(unsigned short reg, u8 *val)
 173 {
 174         return intel_scu_ipc_ioread8(reg, val);
 175 }
 176 EXPORT_SYMBOL_GPL(intel_msic_reg_read);
 177 
 178 /**
 179  * intel_msic_reg_write - write a single MSIC register
 180  * @reg: register to write
 181  * @val: value to write to that register
 182  *
 183  * Write a single MSIC register. Returns 0 on success and negative
 184  * errno in case of failure.
 185  *
 186  * Function may sleep.
 187  */
 188 int intel_msic_reg_write(unsigned short reg, u8 val)
 189 {
 190         return intel_scu_ipc_iowrite8(reg, val);
 191 }
 192 EXPORT_SYMBOL_GPL(intel_msic_reg_write);
 193 
 194 /**
 195  * intel_msic_reg_update - update a single MSIC register
 196  * @reg: register to update
 197  * @val: value to write to the register
 198  * @mask: specifies which of the bits are updated (%0 = don't update,
 199  *        %1 = update)
 200  *
 201  * Perform an update to a register @reg. @mask is used to specify which
 202  * bits are updated. Returns %0 in case of success and negative errno in
 203  * case of failure.
 204  *
 205  * Function may sleep.
 206  */
 207 int intel_msic_reg_update(unsigned short reg, u8 val, u8 mask)
 208 {
 209         return intel_scu_ipc_update_register(reg, val, mask);
 210 }
 211 EXPORT_SYMBOL_GPL(intel_msic_reg_update);
 212 
 213 /**
 214  * intel_msic_bulk_read - read an array of registers
 215  * @reg: array of register addresses to read
 216  * @buf: array where the read values are placed
 217  * @count: number of registers to read
 218  *
 219  * Function reads @count registers from the MSIC using addresses passed in
 220  * @reg. Read values are placed in @buf. Reads are performed atomically
 221  * wrt. MSIC.
 222  *
 223  * Returns %0 in case of success and negative errno in case of failure.
 224  *
 225  * Function may sleep.
 226  */
 227 int intel_msic_bulk_read(unsigned short *reg, u8 *buf, size_t count)
 228 {
 229         if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
 230                 return -EINVAL;
 231 
 232         return intel_scu_ipc_readv(reg, buf, count);
 233 }
 234 EXPORT_SYMBOL_GPL(intel_msic_bulk_read);
 235 
 236 /**
 237  * intel_msic_bulk_write - write an array of values to the MSIC registers
 238  * @reg: array of registers to write
 239  * @buf: values to write to each register
 240  * @count: number of registers to write
 241  *
 242  * Function writes @count registers in @buf to MSIC. Writes are performed
 243  * atomically wrt MSIC. Returns %0 in case of success and negative errno in
 244  * case of failure.
 245  *
 246  * Function may sleep.
 247  */
 248 int intel_msic_bulk_write(unsigned short *reg, u8 *buf, size_t count)
 249 {
 250         if (WARN_ON(count > SCU_IPC_RWBUF_LIMIT))
 251                 return -EINVAL;
 252 
 253         return intel_scu_ipc_writev(reg, buf, count);
 254 }
 255 EXPORT_SYMBOL_GPL(intel_msic_bulk_write);
 256 
 257 /**
 258  * intel_msic_irq_read - read a register from an MSIC interrupt tree
 259  * @msic: MSIC instance
 260  * @reg: interrupt register (between %INTEL_MSIC_IRQLVL1 and
 261  *       %INTEL_MSIC_RESETIRQ2)
 262  * @val: value of the register is placed here
 263  *
 264  * This function can be used by an MSIC subdevice interrupt handler to read
 265  * a register value from the MSIC interrupt tree. In this way subdevice
 266  * drivers don't have to map in the interrupt tree themselves but can just
 267  * call this function instead.
 268  *
 269  * Function doesn't sleep and is callable from interrupt context.
 270  *
 271  * Returns %-EINVAL if @reg is outside of the allowed register region.
 272  */
 273 int intel_msic_irq_read(struct intel_msic *msic, unsigned short reg, u8 *val)
 274 {
 275         if (WARN_ON(reg < INTEL_MSIC_IRQLVL1 || reg > INTEL_MSIC_RESETIRQ2))
 276                 return -EINVAL;
 277 
 278         *val = readb(msic->irq_base + (reg - INTEL_MSIC_IRQLVL1));
 279         return 0;
 280 }
 281 EXPORT_SYMBOL_GPL(intel_msic_irq_read);
 282 
 283 static int intel_msic_init_devices(struct intel_msic *msic)
 284 {
 285         struct platform_device *pdev = msic->pdev;
 286         struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
 287         int ret, i;
 288 
 289         if (pdata->gpio) {
 290                 struct mfd_cell *cell = &msic_devs[INTEL_MSIC_BLOCK_GPIO];
 291 
 292                 cell->platform_data = pdata->gpio;
 293                 cell->pdata_size = sizeof(*pdata->gpio);
 294         }
 295 
 296         if (pdata->ocd) {
 297                 unsigned gpio = pdata->ocd->gpio;
 298 
 299                 ret = devm_gpio_request_one(&pdev->dev, gpio,
 300                                         GPIOF_IN, "ocd_gpio");
 301                 if (ret) {
 302                         dev_err(&pdev->dev, "failed to register OCD GPIO\n");
 303                         return ret;
 304                 }
 305 
 306                 ret = gpio_to_irq(gpio);
 307                 if (ret < 0) {
 308                         dev_err(&pdev->dev, "no IRQ number for OCD GPIO\n");
 309                         return ret;
 310                 }
 311 
 312                 /* Update the IRQ number for the OCD */
 313                 pdata->irq[INTEL_MSIC_BLOCK_OCD] = ret;
 314         }
 315 
 316         for (i = 0; i < ARRAY_SIZE(msic_devs); i++) {
 317                 if (!pdata->irq[i])
 318                         continue;
 319 
 320                 ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
 321                                       pdata->irq[i], NULL);
 322                 if (ret)
 323                         goto fail;
 324         }
 325 
 326         ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
 327                               ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);
 328         if (ret)
 329                 goto fail;
 330 
 331         return 0;
 332 
 333 fail:
 334         mfd_remove_devices(&pdev->dev);
 335 
 336         return ret;
 337 }
 338 
 339 static void intel_msic_remove_devices(struct intel_msic *msic)
 340 {
 341         struct platform_device *pdev = msic->pdev;
 342 
 343         mfd_remove_devices(&pdev->dev);
 344 }
 345 
 346 static int intel_msic_probe(struct platform_device *pdev)
 347 {
 348         struct intel_msic_platform_data *pdata = dev_get_platdata(&pdev->dev);
 349         struct intel_msic *msic;
 350         struct resource *res;
 351         u8 id0, id1;
 352         int ret;
 353 
 354         if (!pdata) {
 355                 dev_err(&pdev->dev, "no platform data passed\n");
 356                 return -EINVAL;
 357         }
 358 
 359         /* First validate that we have an MSIC in place */
 360         ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID0, &id0);
 361         if (ret) {
 362                 dev_err(&pdev->dev, "failed to identify the MSIC chip (ID0)\n");
 363                 return -ENXIO;
 364         }
 365 
 366         ret = intel_scu_ipc_ioread8(INTEL_MSIC_ID1, &id1);
 367         if (ret) {
 368                 dev_err(&pdev->dev, "failed to identify the MSIC chip (ID1)\n");
 369                 return -ENXIO;
 370         }
 371 
 372         if (MSIC_VENDOR(id0) != MSIC_VENDOR(id1)) {
 373                 dev_err(&pdev->dev, "invalid vendor ID: %x, %x\n", id0, id1);
 374                 return -ENXIO;
 375         }
 376 
 377         msic = devm_kzalloc(&pdev->dev, sizeof(*msic), GFP_KERNEL);
 378         if (!msic)
 379                 return -ENOMEM;
 380 
 381         msic->vendor = MSIC_VENDOR(id0);
 382         msic->version = MSIC_VERSION(id0);
 383         msic->pdev = pdev;
 384 
 385         /*
 386          * Map in the MSIC interrupt tree area in SRAM. This is exposed to
 387          * the clients via intel_msic_irq_read().
 388          */
 389         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 390         msic->irq_base = devm_ioremap_resource(&pdev->dev, res);
 391         if (IS_ERR(msic->irq_base))
 392                 return PTR_ERR(msic->irq_base);
 393 
 394         platform_set_drvdata(pdev, msic);
 395 
 396         ret = intel_msic_init_devices(msic);
 397         if (ret) {
 398                 dev_err(&pdev->dev, "failed to initialize MSIC devices\n");
 399                 return ret;
 400         }
 401 
 402         dev_info(&pdev->dev, "Intel MSIC version %c%d (vendor %#x)\n",
 403                  MSIC_MAJOR(msic->version), MSIC_MINOR(msic->version),
 404                  msic->vendor);
 405 
 406         return 0;
 407 }
 408 
 409 static int intel_msic_remove(struct platform_device *pdev)
 410 {
 411         struct intel_msic *msic = platform_get_drvdata(pdev);
 412 
 413         intel_msic_remove_devices(msic);
 414 
 415         return 0;
 416 }
 417 
 418 static struct platform_driver intel_msic_driver = {
 419         .probe          = intel_msic_probe,
 420         .remove         = intel_msic_remove,
 421         .driver         = {
 422                 .name   = "intel_msic",
 423         },
 424 };
 425 builtin_platform_driver(intel_msic_driver);

/* [<][>][^][v][top][bottom][index][help] */