197fb5e8dSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 20b9641f5SGilad Avidov /* 30b9641f5SGilad Avidov * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved. 45a86bf34SKenneth Heitke */ 55a86bf34SKenneth Heitke #include <linux/kernel.h> 65a86bf34SKenneth Heitke #include <linux/errno.h> 75a86bf34SKenneth Heitke #include <linux/idr.h> 85a86bf34SKenneth Heitke #include <linux/slab.h> 95a86bf34SKenneth Heitke #include <linux/module.h> 105a86bf34SKenneth Heitke #include <linux/of.h> 115a86bf34SKenneth Heitke #include <linux/of_device.h> 125a86bf34SKenneth Heitke #include <linux/platform_device.h> 135a86bf34SKenneth Heitke #include <linux/spmi.h> 145a86bf34SKenneth Heitke #include <linux/pm_runtime.h> 155a86bf34SKenneth Heitke 165a86bf34SKenneth Heitke #include <dt-bindings/spmi/spmi.h> 17a9fce374SAnkit Gupta #define CREATE_TRACE_POINTS 18a9fce374SAnkit Gupta #include <trace/events/spmi.h> 195a86bf34SKenneth Heitke 2047f55b74SSudip Mukherjee static bool is_registered; 215a86bf34SKenneth Heitke static DEFINE_IDA(ctrl_ida); 225a86bf34SKenneth Heitke 235a86bf34SKenneth Heitke static void spmi_dev_release(struct device *dev) 245a86bf34SKenneth Heitke { 255a86bf34SKenneth Heitke struct spmi_device *sdev = to_spmi_device(dev); 260be0a733SMauro Carvalho Chehab 275a86bf34SKenneth Heitke kfree(sdev); 285a86bf34SKenneth Heitke } 295a86bf34SKenneth Heitke 305a86bf34SKenneth Heitke static const struct device_type spmi_dev_type = { 315a86bf34SKenneth Heitke .release = spmi_dev_release, 325a86bf34SKenneth Heitke }; 335a86bf34SKenneth Heitke 345a86bf34SKenneth Heitke static void spmi_ctrl_release(struct device *dev) 355a86bf34SKenneth Heitke { 365a86bf34SKenneth Heitke struct spmi_controller *ctrl = to_spmi_controller(dev); 370be0a733SMauro Carvalho Chehab 385a86bf34SKenneth Heitke ida_simple_remove(&ctrl_ida, ctrl->nr); 395a86bf34SKenneth Heitke kfree(ctrl); 405a86bf34SKenneth Heitke } 415a86bf34SKenneth Heitke 425a86bf34SKenneth Heitke static const struct device_type spmi_ctrl_type = { 435a86bf34SKenneth Heitke .release = spmi_ctrl_release, 445a86bf34SKenneth Heitke }; 455a86bf34SKenneth Heitke 465a86bf34SKenneth Heitke static int spmi_device_match(struct device *dev, struct device_driver *drv) 475a86bf34SKenneth Heitke { 485a86bf34SKenneth Heitke if (of_driver_match_device(dev, drv)) 495a86bf34SKenneth Heitke return 1; 505a86bf34SKenneth Heitke 515a86bf34SKenneth Heitke if (drv->name) 525a86bf34SKenneth Heitke return strncmp(dev_name(dev), drv->name, 535a86bf34SKenneth Heitke SPMI_NAME_SIZE) == 0; 545a86bf34SKenneth Heitke 555a86bf34SKenneth Heitke return 0; 565a86bf34SKenneth Heitke } 575a86bf34SKenneth Heitke 585a86bf34SKenneth Heitke /** 595a86bf34SKenneth Heitke * spmi_device_add() - add a device previously constructed via spmi_device_alloc() 605a86bf34SKenneth Heitke * @sdev: spmi_device to be added 615a86bf34SKenneth Heitke */ 625a86bf34SKenneth Heitke int spmi_device_add(struct spmi_device *sdev) 635a86bf34SKenneth Heitke { 645a86bf34SKenneth Heitke struct spmi_controller *ctrl = sdev->ctrl; 655a86bf34SKenneth Heitke int err; 665a86bf34SKenneth Heitke 675a86bf34SKenneth Heitke dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid); 685a86bf34SKenneth Heitke 695a86bf34SKenneth Heitke err = device_add(&sdev->dev); 705a86bf34SKenneth Heitke if (err < 0) { 715a86bf34SKenneth Heitke dev_err(&sdev->dev, "Can't add %s, status %d\n", 725a86bf34SKenneth Heitke dev_name(&sdev->dev), err); 735a86bf34SKenneth Heitke goto err_device_add; 745a86bf34SKenneth Heitke } 755a86bf34SKenneth Heitke 765a86bf34SKenneth Heitke dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev)); 775a86bf34SKenneth Heitke 785a86bf34SKenneth Heitke err_device_add: 795a86bf34SKenneth Heitke return err; 805a86bf34SKenneth Heitke } 815a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_device_add); 825a86bf34SKenneth Heitke 835a86bf34SKenneth Heitke /** 845a86bf34SKenneth Heitke * spmi_device_remove(): remove an SPMI device 855a86bf34SKenneth Heitke * @sdev: spmi_device to be removed 865a86bf34SKenneth Heitke */ 875a86bf34SKenneth Heitke void spmi_device_remove(struct spmi_device *sdev) 885a86bf34SKenneth Heitke { 895a86bf34SKenneth Heitke device_unregister(&sdev->dev); 905a86bf34SKenneth Heitke } 915a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_device_remove); 925a86bf34SKenneth Heitke 935a86bf34SKenneth Heitke static inline int 945a86bf34SKenneth Heitke spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid) 955a86bf34SKenneth Heitke { 96a9fce374SAnkit Gupta int ret; 97a9fce374SAnkit Gupta 985a86bf34SKenneth Heitke if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type) 995a86bf34SKenneth Heitke return -EINVAL; 1005a86bf34SKenneth Heitke 101a9fce374SAnkit Gupta ret = ctrl->cmd(ctrl, opcode, sid); 102a9fce374SAnkit Gupta trace_spmi_cmd(opcode, sid, ret); 103a9fce374SAnkit Gupta return ret; 1045a86bf34SKenneth Heitke } 1055a86bf34SKenneth Heitke 1065a86bf34SKenneth Heitke static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode, 1075a86bf34SKenneth Heitke u8 sid, u16 addr, u8 *buf, size_t len) 1085a86bf34SKenneth Heitke { 109a9fce374SAnkit Gupta int ret; 110a9fce374SAnkit Gupta 1115a86bf34SKenneth Heitke if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type) 1125a86bf34SKenneth Heitke return -EINVAL; 1135a86bf34SKenneth Heitke 114a9fce374SAnkit Gupta trace_spmi_read_begin(opcode, sid, addr); 115a9fce374SAnkit Gupta ret = ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len); 116a9fce374SAnkit Gupta trace_spmi_read_end(opcode, sid, addr, ret, len, buf); 117a9fce374SAnkit Gupta return ret; 1185a86bf34SKenneth Heitke } 1195a86bf34SKenneth Heitke 1205a86bf34SKenneth Heitke static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode, 1215a86bf34SKenneth Heitke u8 sid, u16 addr, const u8 *buf, size_t len) 1225a86bf34SKenneth Heitke { 123a9fce374SAnkit Gupta int ret; 124a9fce374SAnkit Gupta 1255a86bf34SKenneth Heitke if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type) 1265a86bf34SKenneth Heitke return -EINVAL; 1275a86bf34SKenneth Heitke 128a9fce374SAnkit Gupta trace_spmi_write_begin(opcode, sid, addr, len, buf); 129a9fce374SAnkit Gupta ret = ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len); 130a9fce374SAnkit Gupta trace_spmi_write_end(opcode, sid, addr, ret); 131a9fce374SAnkit Gupta return ret; 1325a86bf34SKenneth Heitke } 1335a86bf34SKenneth Heitke 1345a86bf34SKenneth Heitke /** 1355a86bf34SKenneth Heitke * spmi_register_read() - register read 1365a86bf34SKenneth Heitke * @sdev: SPMI device. 1375a86bf34SKenneth Heitke * @addr: slave register address (5-bit address). 1385a86bf34SKenneth Heitke * @buf: buffer to be populated with data from the Slave. 1395a86bf34SKenneth Heitke * 1405a86bf34SKenneth Heitke * Reads 1 byte of data from a Slave device register. 1415a86bf34SKenneth Heitke */ 1425a86bf34SKenneth Heitke int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf) 1435a86bf34SKenneth Heitke { 1445a86bf34SKenneth Heitke /* 5-bit register address */ 1455a86bf34SKenneth Heitke if (addr > 0x1F) 1465a86bf34SKenneth Heitke return -EINVAL; 1475a86bf34SKenneth Heitke 1485a86bf34SKenneth Heitke return spmi_read_cmd(sdev->ctrl, SPMI_CMD_READ, sdev->usid, addr, 1495a86bf34SKenneth Heitke buf, 1); 1505a86bf34SKenneth Heitke } 1515a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_register_read); 1525a86bf34SKenneth Heitke 1535a86bf34SKenneth Heitke /** 1545a86bf34SKenneth Heitke * spmi_ext_register_read() - extended register read 1555a86bf34SKenneth Heitke * @sdev: SPMI device. 1565a86bf34SKenneth Heitke * @addr: slave register address (8-bit address). 1575a86bf34SKenneth Heitke * @buf: buffer to be populated with data from the Slave. 1585a86bf34SKenneth Heitke * @len: the request number of bytes to read (up to 16 bytes). 1595a86bf34SKenneth Heitke * 1605a86bf34SKenneth Heitke * Reads up to 16 bytes of data from the extended register space on a 1615a86bf34SKenneth Heitke * Slave device. 1625a86bf34SKenneth Heitke */ 1635a86bf34SKenneth Heitke int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, 1645a86bf34SKenneth Heitke size_t len) 1655a86bf34SKenneth Heitke { 1665a86bf34SKenneth Heitke /* 8-bit register address, up to 16 bytes */ 1675a86bf34SKenneth Heitke if (len == 0 || len > 16) 1685a86bf34SKenneth Heitke return -EINVAL; 1695a86bf34SKenneth Heitke 1705a86bf34SKenneth Heitke return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READ, sdev->usid, addr, 1715a86bf34SKenneth Heitke buf, len); 1725a86bf34SKenneth Heitke } 1735a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_ext_register_read); 1745a86bf34SKenneth Heitke 1755a86bf34SKenneth Heitke /** 1765a86bf34SKenneth Heitke * spmi_ext_register_readl() - extended register read long 1775a86bf34SKenneth Heitke * @sdev: SPMI device. 1785a86bf34SKenneth Heitke * @addr: slave register address (16-bit address). 1795a86bf34SKenneth Heitke * @buf: buffer to be populated with data from the Slave. 1805a86bf34SKenneth Heitke * @len: the request number of bytes to read (up to 8 bytes). 1815a86bf34SKenneth Heitke * 1825a86bf34SKenneth Heitke * Reads up to 8 bytes of data from the extended register space on a 1835a86bf34SKenneth Heitke * Slave device using 16-bit address. 1845a86bf34SKenneth Heitke */ 1855a86bf34SKenneth Heitke int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf, 1865a86bf34SKenneth Heitke size_t len) 1875a86bf34SKenneth Heitke { 1885a86bf34SKenneth Heitke /* 16-bit register address, up to 8 bytes */ 1895a86bf34SKenneth Heitke if (len == 0 || len > 8) 1905a86bf34SKenneth Heitke return -EINVAL; 1915a86bf34SKenneth Heitke 1925a86bf34SKenneth Heitke return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READL, sdev->usid, addr, 1935a86bf34SKenneth Heitke buf, len); 1945a86bf34SKenneth Heitke } 1955a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_ext_register_readl); 1965a86bf34SKenneth Heitke 1975a86bf34SKenneth Heitke /** 1985a86bf34SKenneth Heitke * spmi_register_write() - register write 1995a86bf34SKenneth Heitke * @sdev: SPMI device 2005a86bf34SKenneth Heitke * @addr: slave register address (5-bit address). 2015a86bf34SKenneth Heitke * @data: buffer containing the data to be transferred to the Slave. 2025a86bf34SKenneth Heitke * 2035a86bf34SKenneth Heitke * Writes 1 byte of data to a Slave device register. 2045a86bf34SKenneth Heitke */ 2055a86bf34SKenneth Heitke int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data) 2065a86bf34SKenneth Heitke { 2075a86bf34SKenneth Heitke /* 5-bit register address */ 2085a86bf34SKenneth Heitke if (addr > 0x1F) 2095a86bf34SKenneth Heitke return -EINVAL; 2105a86bf34SKenneth Heitke 2115a86bf34SKenneth Heitke return spmi_write_cmd(sdev->ctrl, SPMI_CMD_WRITE, sdev->usid, addr, 2125a86bf34SKenneth Heitke &data, 1); 2135a86bf34SKenneth Heitke } 2145a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_register_write); 2155a86bf34SKenneth Heitke 2165a86bf34SKenneth Heitke /** 2175a86bf34SKenneth Heitke * spmi_register_zero_write() - register zero write 2185a86bf34SKenneth Heitke * @sdev: SPMI device. 2195a86bf34SKenneth Heitke * @data: the data to be written to register 0 (7-bits). 2205a86bf34SKenneth Heitke * 2215a86bf34SKenneth Heitke * Writes data to register 0 of the Slave device. 2225a86bf34SKenneth Heitke */ 2235a86bf34SKenneth Heitke int spmi_register_zero_write(struct spmi_device *sdev, u8 data) 2245a86bf34SKenneth Heitke { 2255a86bf34SKenneth Heitke return spmi_write_cmd(sdev->ctrl, SPMI_CMD_ZERO_WRITE, sdev->usid, 0, 2265a86bf34SKenneth Heitke &data, 1); 2275a86bf34SKenneth Heitke } 2285a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_register_zero_write); 2295a86bf34SKenneth Heitke 2305a86bf34SKenneth Heitke /** 2315a86bf34SKenneth Heitke * spmi_ext_register_write() - extended register write 2325a86bf34SKenneth Heitke * @sdev: SPMI device. 2335a86bf34SKenneth Heitke * @addr: slave register address (8-bit address). 2345a86bf34SKenneth Heitke * @buf: buffer containing the data to be transferred to the Slave. 2355a86bf34SKenneth Heitke * @len: the request number of bytes to read (up to 16 bytes). 2365a86bf34SKenneth Heitke * 2375a86bf34SKenneth Heitke * Writes up to 16 bytes of data to the extended register space of a 2385a86bf34SKenneth Heitke * Slave device. 2395a86bf34SKenneth Heitke */ 2405a86bf34SKenneth Heitke int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, const u8 *buf, 2415a86bf34SKenneth Heitke size_t len) 2425a86bf34SKenneth Heitke { 2435a86bf34SKenneth Heitke /* 8-bit register address, up to 16 bytes */ 2445a86bf34SKenneth Heitke if (len == 0 || len > 16) 2455a86bf34SKenneth Heitke return -EINVAL; 2465a86bf34SKenneth Heitke 2475a86bf34SKenneth Heitke return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITE, sdev->usid, addr, 2485a86bf34SKenneth Heitke buf, len); 2495a86bf34SKenneth Heitke } 2505a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_ext_register_write); 2515a86bf34SKenneth Heitke 2525a86bf34SKenneth Heitke /** 2535a86bf34SKenneth Heitke * spmi_ext_register_writel() - extended register write long 2545a86bf34SKenneth Heitke * @sdev: SPMI device. 2555a86bf34SKenneth Heitke * @addr: slave register address (16-bit address). 2565a86bf34SKenneth Heitke * @buf: buffer containing the data to be transferred to the Slave. 2575a86bf34SKenneth Heitke * @len: the request number of bytes to read (up to 8 bytes). 2585a86bf34SKenneth Heitke * 2595a86bf34SKenneth Heitke * Writes up to 8 bytes of data to the extended register space of a 2605a86bf34SKenneth Heitke * Slave device using 16-bit address. 2615a86bf34SKenneth Heitke */ 2625a86bf34SKenneth Heitke int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, const u8 *buf, 2635a86bf34SKenneth Heitke size_t len) 2645a86bf34SKenneth Heitke { 2655a86bf34SKenneth Heitke /* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */ 2665a86bf34SKenneth Heitke if (len == 0 || len > 8) 2675a86bf34SKenneth Heitke return -EINVAL; 2685a86bf34SKenneth Heitke 2695a86bf34SKenneth Heitke return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITEL, sdev->usid, 2705a86bf34SKenneth Heitke addr, buf, len); 2715a86bf34SKenneth Heitke } 2725a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_ext_register_writel); 2735a86bf34SKenneth Heitke 2745a86bf34SKenneth Heitke /** 2755a86bf34SKenneth Heitke * spmi_command_reset() - sends RESET command to the specified slave 2765a86bf34SKenneth Heitke * @sdev: SPMI device. 2775a86bf34SKenneth Heitke * 2785a86bf34SKenneth Heitke * The Reset command initializes the Slave and forces all registers to 2795a86bf34SKenneth Heitke * their reset values. The Slave shall enter the STARTUP state after 2805a86bf34SKenneth Heitke * receiving a Reset command. 2815a86bf34SKenneth Heitke */ 2825a86bf34SKenneth Heitke int spmi_command_reset(struct spmi_device *sdev) 2835a86bf34SKenneth Heitke { 2845a86bf34SKenneth Heitke return spmi_cmd(sdev->ctrl, SPMI_CMD_RESET, sdev->usid); 2855a86bf34SKenneth Heitke } 2865a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_command_reset); 2875a86bf34SKenneth Heitke 2885a86bf34SKenneth Heitke /** 2895a86bf34SKenneth Heitke * spmi_command_sleep() - sends SLEEP command to the specified SPMI device 2905a86bf34SKenneth Heitke * @sdev: SPMI device. 2915a86bf34SKenneth Heitke * 2925a86bf34SKenneth Heitke * The Sleep command causes the Slave to enter the user defined SLEEP state. 2935a86bf34SKenneth Heitke */ 2945a86bf34SKenneth Heitke int spmi_command_sleep(struct spmi_device *sdev) 2955a86bf34SKenneth Heitke { 2965a86bf34SKenneth Heitke return spmi_cmd(sdev->ctrl, SPMI_CMD_SLEEP, sdev->usid); 2975a86bf34SKenneth Heitke } 2985a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_command_sleep); 2995a86bf34SKenneth Heitke 3005a86bf34SKenneth Heitke /** 3015a86bf34SKenneth Heitke * spmi_command_wakeup() - sends WAKEUP command to the specified SPMI device 3025a86bf34SKenneth Heitke * @sdev: SPMI device. 3035a86bf34SKenneth Heitke * 3045a86bf34SKenneth Heitke * The Wakeup command causes the Slave to move from the SLEEP state to 3055a86bf34SKenneth Heitke * the ACTIVE state. 3065a86bf34SKenneth Heitke */ 3075a86bf34SKenneth Heitke int spmi_command_wakeup(struct spmi_device *sdev) 3085a86bf34SKenneth Heitke { 3095a86bf34SKenneth Heitke return spmi_cmd(sdev->ctrl, SPMI_CMD_WAKEUP, sdev->usid); 3105a86bf34SKenneth Heitke } 3115a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_command_wakeup); 3125a86bf34SKenneth Heitke 3135a86bf34SKenneth Heitke /** 3145a86bf34SKenneth Heitke * spmi_command_shutdown() - sends SHUTDOWN command to the specified SPMI device 3155a86bf34SKenneth Heitke * @sdev: SPMI device. 3165a86bf34SKenneth Heitke * 3175a86bf34SKenneth Heitke * The Shutdown command causes the Slave to enter the SHUTDOWN state. 3185a86bf34SKenneth Heitke */ 3195a86bf34SKenneth Heitke int spmi_command_shutdown(struct spmi_device *sdev) 3205a86bf34SKenneth Heitke { 3215a86bf34SKenneth Heitke return spmi_cmd(sdev->ctrl, SPMI_CMD_SHUTDOWN, sdev->usid); 3225a86bf34SKenneth Heitke } 3235a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_command_shutdown); 3245a86bf34SKenneth Heitke 3255a86bf34SKenneth Heitke static int spmi_drv_probe(struct device *dev) 3265a86bf34SKenneth Heitke { 3275a86bf34SKenneth Heitke const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); 3285a86bf34SKenneth Heitke struct spmi_device *sdev = to_spmi_device(dev); 3295a86bf34SKenneth Heitke int err; 3305a86bf34SKenneth Heitke 3315a86bf34SKenneth Heitke pm_runtime_get_noresume(dev); 3325a86bf34SKenneth Heitke pm_runtime_set_active(dev); 3335a86bf34SKenneth Heitke pm_runtime_enable(dev); 3345a86bf34SKenneth Heitke 3355a86bf34SKenneth Heitke err = sdrv->probe(sdev); 3365a86bf34SKenneth Heitke if (err) 3375a86bf34SKenneth Heitke goto fail_probe; 3385a86bf34SKenneth Heitke 3395a86bf34SKenneth Heitke return 0; 3405a86bf34SKenneth Heitke 3415a86bf34SKenneth Heitke fail_probe: 3425a86bf34SKenneth Heitke pm_runtime_disable(dev); 3435a86bf34SKenneth Heitke pm_runtime_set_suspended(dev); 3445a86bf34SKenneth Heitke pm_runtime_put_noidle(dev); 3455a86bf34SKenneth Heitke return err; 3465a86bf34SKenneth Heitke } 3475a86bf34SKenneth Heitke 348fc7a6209SUwe Kleine-König static void spmi_drv_remove(struct device *dev) 3495a86bf34SKenneth Heitke { 3505a86bf34SKenneth Heitke const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); 3515a86bf34SKenneth Heitke 3525a86bf34SKenneth Heitke pm_runtime_get_sync(dev); 3535a86bf34SKenneth Heitke sdrv->remove(to_spmi_device(dev)); 3545a86bf34SKenneth Heitke pm_runtime_put_noidle(dev); 3555a86bf34SKenneth Heitke 3565a86bf34SKenneth Heitke pm_runtime_disable(dev); 3575a86bf34SKenneth Heitke pm_runtime_set_suspended(dev); 3585a86bf34SKenneth Heitke pm_runtime_put_noidle(dev); 3595a86bf34SKenneth Heitke } 3605a86bf34SKenneth Heitke 361d40c2d4eSHsin-Hsiung Wang static void spmi_drv_shutdown(struct device *dev) 362d40c2d4eSHsin-Hsiung Wang { 363d40c2d4eSHsin-Hsiung Wang const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); 364d40c2d4eSHsin-Hsiung Wang 365d40c2d4eSHsin-Hsiung Wang if (sdrv && sdrv->shutdown) 366d40c2d4eSHsin-Hsiung Wang sdrv->shutdown(to_spmi_device(dev)); 367d40c2d4eSHsin-Hsiung Wang } 368d40c2d4eSHsin-Hsiung Wang 369d50daa2aSBjorn Andersson static int spmi_drv_uevent(struct device *dev, struct kobj_uevent_env *env) 370d50daa2aSBjorn Andersson { 371d50daa2aSBjorn Andersson int ret; 372d50daa2aSBjorn Andersson 373d50daa2aSBjorn Andersson ret = of_device_uevent_modalias(dev, env); 374d50daa2aSBjorn Andersson if (ret != -ENODEV) 375d50daa2aSBjorn Andersson return ret; 376d50daa2aSBjorn Andersson 377d50daa2aSBjorn Andersson return 0; 378d50daa2aSBjorn Andersson } 379d50daa2aSBjorn Andersson 3805a86bf34SKenneth Heitke static struct bus_type spmi_bus_type = { 3815a86bf34SKenneth Heitke .name = "spmi", 3825a86bf34SKenneth Heitke .match = spmi_device_match, 3835a86bf34SKenneth Heitke .probe = spmi_drv_probe, 3845a86bf34SKenneth Heitke .remove = spmi_drv_remove, 385d40c2d4eSHsin-Hsiung Wang .shutdown = spmi_drv_shutdown, 386d50daa2aSBjorn Andersson .uevent = spmi_drv_uevent, 3875a86bf34SKenneth Heitke }; 3885a86bf34SKenneth Heitke 3895a86bf34SKenneth Heitke /** 390*9a2139c2SCaleb Connolly * spmi_device_from_of() - get the associated SPMI device from a device node 391*9a2139c2SCaleb Connolly * 392*9a2139c2SCaleb Connolly * @np: device node 393*9a2139c2SCaleb Connolly * 394*9a2139c2SCaleb Connolly * Returns the struct spmi_device associated with a device node or NULL. 395*9a2139c2SCaleb Connolly */ 396*9a2139c2SCaleb Connolly struct spmi_device *spmi_device_from_of(struct device_node *np) 397*9a2139c2SCaleb Connolly { 398*9a2139c2SCaleb Connolly struct device *dev = bus_find_device_by_of_node(&spmi_bus_type, np); 399*9a2139c2SCaleb Connolly 400*9a2139c2SCaleb Connolly if (dev) 401*9a2139c2SCaleb Connolly return to_spmi_device(dev); 402*9a2139c2SCaleb Connolly return NULL; 403*9a2139c2SCaleb Connolly } 404*9a2139c2SCaleb Connolly EXPORT_SYMBOL_GPL(spmi_device_from_of); 405*9a2139c2SCaleb Connolly 406*9a2139c2SCaleb Connolly /** 4075a86bf34SKenneth Heitke * spmi_controller_alloc() - Allocate a new SPMI device 4085a86bf34SKenneth Heitke * @ctrl: associated controller 4095a86bf34SKenneth Heitke * 4105a86bf34SKenneth Heitke * Caller is responsible for either calling spmi_device_add() to add the 4115a86bf34SKenneth Heitke * newly allocated controller, or calling spmi_device_put() to discard it. 4125a86bf34SKenneth Heitke */ 4135a86bf34SKenneth Heitke struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl) 4145a86bf34SKenneth Heitke { 4155a86bf34SKenneth Heitke struct spmi_device *sdev; 4165a86bf34SKenneth Heitke 4175a86bf34SKenneth Heitke sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); 4185a86bf34SKenneth Heitke if (!sdev) 4195a86bf34SKenneth Heitke return NULL; 4205a86bf34SKenneth Heitke 4215a86bf34SKenneth Heitke sdev->ctrl = ctrl; 4225a86bf34SKenneth Heitke device_initialize(&sdev->dev); 4235a86bf34SKenneth Heitke sdev->dev.parent = &ctrl->dev; 4245a86bf34SKenneth Heitke sdev->dev.bus = &spmi_bus_type; 4255a86bf34SKenneth Heitke sdev->dev.type = &spmi_dev_type; 4265a86bf34SKenneth Heitke return sdev; 4275a86bf34SKenneth Heitke } 4285a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_device_alloc); 4295a86bf34SKenneth Heitke 4305a86bf34SKenneth Heitke /** 4315a86bf34SKenneth Heitke * spmi_controller_alloc() - Allocate a new SPMI controller 4325a86bf34SKenneth Heitke * @parent: parent device 4335a86bf34SKenneth Heitke * @size: size of private data 4345a86bf34SKenneth Heitke * 4355a86bf34SKenneth Heitke * Caller is responsible for either calling spmi_controller_add() to add the 4365a86bf34SKenneth Heitke * newly allocated controller, or calling spmi_controller_put() to discard it. 4375a86bf34SKenneth Heitke * The allocated private data region may be accessed via 4385a86bf34SKenneth Heitke * spmi_controller_get_drvdata() 4395a86bf34SKenneth Heitke */ 4405a86bf34SKenneth Heitke struct spmi_controller *spmi_controller_alloc(struct device *parent, 4415a86bf34SKenneth Heitke size_t size) 4425a86bf34SKenneth Heitke { 4435a86bf34SKenneth Heitke struct spmi_controller *ctrl; 4445a86bf34SKenneth Heitke int id; 4455a86bf34SKenneth Heitke 4465a86bf34SKenneth Heitke if (WARN_ON(!parent)) 4475a86bf34SKenneth Heitke return NULL; 4485a86bf34SKenneth Heitke 4495a86bf34SKenneth Heitke ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL); 4505a86bf34SKenneth Heitke if (!ctrl) 4515a86bf34SKenneth Heitke return NULL; 4525a86bf34SKenneth Heitke 4535a86bf34SKenneth Heitke device_initialize(&ctrl->dev); 4545a86bf34SKenneth Heitke ctrl->dev.type = &spmi_ctrl_type; 4555a86bf34SKenneth Heitke ctrl->dev.bus = &spmi_bus_type; 4565a86bf34SKenneth Heitke ctrl->dev.parent = parent; 4575a86bf34SKenneth Heitke ctrl->dev.of_node = parent->of_node; 4585a86bf34SKenneth Heitke spmi_controller_set_drvdata(ctrl, &ctrl[1]); 4595a86bf34SKenneth Heitke 4605a86bf34SKenneth Heitke id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); 4615a86bf34SKenneth Heitke if (id < 0) { 4625a86bf34SKenneth Heitke dev_err(parent, 4635a86bf34SKenneth Heitke "unable to allocate SPMI controller identifier.\n"); 4645a86bf34SKenneth Heitke spmi_controller_put(ctrl); 4655a86bf34SKenneth Heitke return NULL; 4665a86bf34SKenneth Heitke } 4675a86bf34SKenneth Heitke 4685a86bf34SKenneth Heitke ctrl->nr = id; 4695a86bf34SKenneth Heitke dev_set_name(&ctrl->dev, "spmi-%d", id); 4705a86bf34SKenneth Heitke 4715a86bf34SKenneth Heitke dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id); 4725a86bf34SKenneth Heitke return ctrl; 4735a86bf34SKenneth Heitke } 4745a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_controller_alloc); 4755a86bf34SKenneth Heitke 4765a86bf34SKenneth Heitke static void of_spmi_register_devices(struct spmi_controller *ctrl) 4775a86bf34SKenneth Heitke { 4785a86bf34SKenneth Heitke struct device_node *node; 4795a86bf34SKenneth Heitke int err; 4805a86bf34SKenneth Heitke 4815a86bf34SKenneth Heitke if (!ctrl->dev.of_node) 4825a86bf34SKenneth Heitke return; 4835a86bf34SKenneth Heitke 4845a86bf34SKenneth Heitke for_each_available_child_of_node(ctrl->dev.of_node, node) { 4855a86bf34SKenneth Heitke struct spmi_device *sdev; 4865a86bf34SKenneth Heitke u32 reg[2]; 4875a86bf34SKenneth Heitke 488e55fe64aSRob Herring dev_dbg(&ctrl->dev, "adding child %pOF\n", node); 4895a86bf34SKenneth Heitke 4905a86bf34SKenneth Heitke err = of_property_read_u32_array(node, "reg", reg, 2); 4915a86bf34SKenneth Heitke if (err) { 4925a86bf34SKenneth Heitke dev_err(&ctrl->dev, 493e55fe64aSRob Herring "node %pOF err (%d) does not have 'reg' property\n", 494e55fe64aSRob Herring node, err); 4955a86bf34SKenneth Heitke continue; 4965a86bf34SKenneth Heitke } 4975a86bf34SKenneth Heitke 4985a86bf34SKenneth Heitke if (reg[1] != SPMI_USID) { 4995a86bf34SKenneth Heitke dev_err(&ctrl->dev, 500e55fe64aSRob Herring "node %pOF contains unsupported 'reg' entry\n", 501e55fe64aSRob Herring node); 5025a86bf34SKenneth Heitke continue; 5035a86bf34SKenneth Heitke } 5045a86bf34SKenneth Heitke 5055a86bf34SKenneth Heitke if (reg[0] >= SPMI_MAX_SLAVE_ID) { 506e55fe64aSRob Herring dev_err(&ctrl->dev, "invalid usid on node %pOF\n", node); 5075a86bf34SKenneth Heitke continue; 5085a86bf34SKenneth Heitke } 5095a86bf34SKenneth Heitke 5105a86bf34SKenneth Heitke dev_dbg(&ctrl->dev, "read usid %02x\n", reg[0]); 5115a86bf34SKenneth Heitke 5125a86bf34SKenneth Heitke sdev = spmi_device_alloc(ctrl); 5135a86bf34SKenneth Heitke if (!sdev) 5145a86bf34SKenneth Heitke continue; 5155a86bf34SKenneth Heitke 5165a86bf34SKenneth Heitke sdev->dev.of_node = node; 5175a86bf34SKenneth Heitke sdev->usid = (u8)reg[0]; 5185a86bf34SKenneth Heitke 5195a86bf34SKenneth Heitke err = spmi_device_add(sdev); 5205a86bf34SKenneth Heitke if (err) { 5215a86bf34SKenneth Heitke dev_err(&sdev->dev, 5225a86bf34SKenneth Heitke "failure adding device. status %d\n", err); 5235a86bf34SKenneth Heitke spmi_device_put(sdev); 5245a86bf34SKenneth Heitke } 5255a86bf34SKenneth Heitke } 5265a86bf34SKenneth Heitke } 5275a86bf34SKenneth Heitke 5285a86bf34SKenneth Heitke /** 5295a86bf34SKenneth Heitke * spmi_controller_add() - Add an SPMI controller 5305a86bf34SKenneth Heitke * @ctrl: controller to be registered. 5315a86bf34SKenneth Heitke * 5325a86bf34SKenneth Heitke * Register a controller previously allocated via spmi_controller_alloc() with 5335a86bf34SKenneth Heitke * the SPMI core. 5345a86bf34SKenneth Heitke */ 5355a86bf34SKenneth Heitke int spmi_controller_add(struct spmi_controller *ctrl) 5365a86bf34SKenneth Heitke { 5375a86bf34SKenneth Heitke int ret; 5385a86bf34SKenneth Heitke 5395a86bf34SKenneth Heitke /* Can't register until after driver model init */ 54047f55b74SSudip Mukherjee if (WARN_ON(!is_registered)) 5415a86bf34SKenneth Heitke return -EAGAIN; 5425a86bf34SKenneth Heitke 5435a86bf34SKenneth Heitke ret = device_add(&ctrl->dev); 5445a86bf34SKenneth Heitke if (ret) 5455a86bf34SKenneth Heitke return ret; 5465a86bf34SKenneth Heitke 5475a86bf34SKenneth Heitke if (IS_ENABLED(CONFIG_OF)) 5485a86bf34SKenneth Heitke of_spmi_register_devices(ctrl); 5495a86bf34SKenneth Heitke 5505a86bf34SKenneth Heitke dev_dbg(&ctrl->dev, "spmi-%d registered: dev:%p\n", 5515a86bf34SKenneth Heitke ctrl->nr, &ctrl->dev); 5525a86bf34SKenneth Heitke 5535a86bf34SKenneth Heitke return 0; 5545a86bf34SKenneth Heitke }; 5555a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_controller_add); 5565a86bf34SKenneth Heitke 5575a86bf34SKenneth Heitke /* Remove a device associated with a controller */ 5585a86bf34SKenneth Heitke static int spmi_ctrl_remove_device(struct device *dev, void *data) 5595a86bf34SKenneth Heitke { 5605a86bf34SKenneth Heitke struct spmi_device *spmidev = to_spmi_device(dev); 5610be0a733SMauro Carvalho Chehab 5625a86bf34SKenneth Heitke if (dev->type == &spmi_dev_type) 5635a86bf34SKenneth Heitke spmi_device_remove(spmidev); 5645a86bf34SKenneth Heitke return 0; 5655a86bf34SKenneth Heitke } 5665a86bf34SKenneth Heitke 5675a86bf34SKenneth Heitke /** 5685a86bf34SKenneth Heitke * spmi_controller_remove(): remove an SPMI controller 5695a86bf34SKenneth Heitke * @ctrl: controller to remove 5705a86bf34SKenneth Heitke * 5715a86bf34SKenneth Heitke * Remove a SPMI controller. Caller is responsible for calling 5725a86bf34SKenneth Heitke * spmi_controller_put() to discard the allocated controller. 5735a86bf34SKenneth Heitke */ 5745a86bf34SKenneth Heitke void spmi_controller_remove(struct spmi_controller *ctrl) 5755a86bf34SKenneth Heitke { 5765a86bf34SKenneth Heitke if (!ctrl) 5775a86bf34SKenneth Heitke return; 5785a86bf34SKenneth Heitke 579b1f0aeecSMauro Carvalho Chehab device_for_each_child(&ctrl->dev, NULL, spmi_ctrl_remove_device); 5805a86bf34SKenneth Heitke device_del(&ctrl->dev); 5815a86bf34SKenneth Heitke } 5825a86bf34SKenneth Heitke EXPORT_SYMBOL_GPL(spmi_controller_remove); 5835a86bf34SKenneth Heitke 5845a86bf34SKenneth Heitke /** 5855a86bf34SKenneth Heitke * spmi_driver_register() - Register client driver with SPMI core 5865a86bf34SKenneth Heitke * @sdrv: client driver to be associated with client-device. 5875a86bf34SKenneth Heitke * 5885a86bf34SKenneth Heitke * This API will register the client driver with the SPMI framework. 5895a86bf34SKenneth Heitke * It is typically called from the driver's module-init function. 5905a86bf34SKenneth Heitke */ 591ff6f4648SStephen Boyd int __spmi_driver_register(struct spmi_driver *sdrv, struct module *owner) 5925a86bf34SKenneth Heitke { 5935a86bf34SKenneth Heitke sdrv->driver.bus = &spmi_bus_type; 594ff6f4648SStephen Boyd sdrv->driver.owner = owner; 5955a86bf34SKenneth Heitke return driver_register(&sdrv->driver); 5965a86bf34SKenneth Heitke } 597ff6f4648SStephen Boyd EXPORT_SYMBOL_GPL(__spmi_driver_register); 5985a86bf34SKenneth Heitke 5995a86bf34SKenneth Heitke static void __exit spmi_exit(void) 6005a86bf34SKenneth Heitke { 6015a86bf34SKenneth Heitke bus_unregister(&spmi_bus_type); 6025a86bf34SKenneth Heitke } 6035a86bf34SKenneth Heitke module_exit(spmi_exit); 6045a86bf34SKenneth Heitke 6055a86bf34SKenneth Heitke static int __init spmi_init(void) 6065a86bf34SKenneth Heitke { 60747f55b74SSudip Mukherjee int ret; 60847f55b74SSudip Mukherjee 60947f55b74SSudip Mukherjee ret = bus_register(&spmi_bus_type); 61047f55b74SSudip Mukherjee if (ret) 61147f55b74SSudip Mukherjee return ret; 61247f55b74SSudip Mukherjee 61347f55b74SSudip Mukherjee is_registered = true; 61447f55b74SSudip Mukherjee return 0; 6155a86bf34SKenneth Heitke } 6165a86bf34SKenneth Heitke postcore_initcall(spmi_init); 6175a86bf34SKenneth Heitke 6185a86bf34SKenneth Heitke MODULE_LICENSE("GPL v2"); 6195a86bf34SKenneth Heitke MODULE_DESCRIPTION("SPMI module"); 6205a86bf34SKenneth Heitke MODULE_ALIAS("platform:spmi"); 621