Lines Matching +full:stmfx +full:- +full:0300 +full:- +full:pinctrl
1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for STMicroelectronics Multi-Function eXpander (STMFX) core
13 #include <linux/mfd/stmfx.h>
78 .of_compatible = "st,stmfx-0300-pinctrl",
79 .name = "stmfx-pinctrl",
84 .of_compatible = "st,stmfx-0300-idd",
85 .name = "stmfx-idd",
90 .of_compatible = "st,stmfx-0300-ts",
91 .name = "stmfx-ts",
116 int stmfx_function_enable(struct stmfx *stmfx, u32 func) in stmfx_function_enable() argument
122 ret = regmap_read(stmfx->map, STMFX_REG_SYS_CTRL, &sys_ctrl); in stmfx_function_enable()
127 * IDD and TS have priority in STMFX FW, so if IDD and TS are enabled, in stmfx_function_enable()
128 * ALTGPIO function is disabled by STMFX FW. If IDD or TS is enabled, in stmfx_function_enable()
134 dev_err(stmfx->dev, "ALTGPIO function already enabled\n"); in stmfx_function_enable()
135 return -EBUSY; in stmfx_function_enable()
141 dev_err(stmfx->dev, "TS in use, aGPIO[3:0] unavailable\n"); in stmfx_function_enable()
142 return -EBUSY; in stmfx_function_enable()
148 dev_err(stmfx->dev, "IDD in use, aGPIO[7:4] unavailable\n"); in stmfx_function_enable()
149 return -EBUSY; in stmfx_function_enable()
154 return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, mask); in stmfx_function_enable()
158 int stmfx_function_disable(struct stmfx *stmfx, u32 func) in stmfx_function_disable() argument
162 return regmap_update_bits(stmfx->map, STMFX_REG_SYS_CTRL, mask, 0); in stmfx_function_disable()
168 struct stmfx *stmfx = irq_data_get_irq_chip_data(data); in stmfx_irq_bus_lock() local
170 mutex_lock(&stmfx->lock); in stmfx_irq_bus_lock()
175 struct stmfx *stmfx = irq_data_get_irq_chip_data(data); in stmfx_irq_bus_sync_unlock() local
177 regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, stmfx->irq_src); in stmfx_irq_bus_sync_unlock()
179 mutex_unlock(&stmfx->lock); in stmfx_irq_bus_sync_unlock()
184 struct stmfx *stmfx = irq_data_get_irq_chip_data(data); in stmfx_irq_mask() local
186 stmfx->irq_src &= ~BIT(data->hwirq % 8); in stmfx_irq_mask()
191 struct stmfx *stmfx = irq_data_get_irq_chip_data(data); in stmfx_irq_unmask() local
193 stmfx->irq_src |= BIT(data->hwirq % 8); in stmfx_irq_unmask()
197 .name = "stmfx-core",
206 struct stmfx *stmfx = data; in stmfx_irq_handler() local
211 ret = regmap_read(stmfx->map, STMFX_REG_IRQ_PENDING, &pending); in stmfx_irq_handler()
221 ret = regmap_write(stmfx->map, STMFX_REG_IRQ_ACK, ack); in stmfx_irq_handler()
228 handle_nested_irq(irq_find_mapping(stmfx->irq_domain, n)); in stmfx_irq_handler()
236 irq_set_chip_data(virq, d->host_data); in stmfx_irq_map()
257 struct stmfx *stmfx = i2c_get_clientdata(client); in stmfx_irq_exit() local
261 irq_dispose_mapping(irq_find_mapping(stmfx->irq_domain, hwirq)); in stmfx_irq_exit()
263 irq_domain_remove(stmfx->irq_domain); in stmfx_irq_exit()
268 struct stmfx *stmfx = i2c_get_clientdata(client); in stmfx_irq_init() local
272 stmfx->irq_domain = irq_domain_add_simple(stmfx->dev->of_node, in stmfx_irq_init()
274 &stmfx_irq_ops, stmfx); in stmfx_irq_init()
275 if (!stmfx->irq_domain) { in stmfx_irq_init()
276 dev_err(stmfx->dev, "Failed to create IRQ domain\n"); in stmfx_irq_init()
277 return -EINVAL; in stmfx_irq_init()
280 if (!of_property_read_bool(stmfx->dev->of_node, "drive-open-drain")) in stmfx_irq_init()
283 irqtrigger = irq_get_trigger_type(client->irq); in stmfx_irq_init()
288 ret = regmap_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, irqoutpin); in stmfx_irq_init()
292 ret = devm_request_threaded_irq(stmfx->dev, client->irq, in stmfx_irq_init()
295 "stmfx", stmfx); in stmfx_irq_init()
299 stmfx->irq = client->irq; in stmfx_irq_init()
309 static int stmfx_chip_reset(struct stmfx *stmfx) in stmfx_chip_reset() argument
313 ret = regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, in stmfx_chip_reset()
325 struct stmfx *stmfx = i2c_get_clientdata(client); in stmfx_chip_init() local
330 stmfx->vdd = devm_regulator_get_optional(&client->dev, "vdd"); in stmfx_chip_init()
331 ret = PTR_ERR_OR_ZERO(stmfx->vdd); in stmfx_chip_init()
333 if (ret == -ENODEV) in stmfx_chip_init()
334 stmfx->vdd = NULL; in stmfx_chip_init()
336 return dev_err_probe(&client->dev, ret, "Failed to get VDD regulator\n"); in stmfx_chip_init()
339 if (stmfx->vdd) { in stmfx_chip_init()
340 ret = regulator_enable(stmfx->vdd); in stmfx_chip_init()
342 dev_err(&client->dev, "VDD enable failed: %d\n", ret); in stmfx_chip_init()
347 ret = regmap_read(stmfx->map, STMFX_REG_CHIP_ID, &id); in stmfx_chip_init()
349 dev_err(&client->dev, "Error reading chip ID: %d\n", ret); in stmfx_chip_init()
355 * STMFX I2C address follows the 7-bit format (MSB), that's why in stmfx_chip_init()
356 * client->addr is shifted. in stmfx_chip_init()
358 * STMFX_I2C_ADDR| STMFX | Linux in stmfx_chip_init()
360 *--------------------------------------------------------- in stmfx_chip_init()
364 if (FIELD_GET(STMFX_REG_CHIP_ID_MASK, ~id) != (client->addr << 1)) { in stmfx_chip_init()
365 dev_err(&client->dev, "Unknown chip ID: %#x\n", id); in stmfx_chip_init()
366 ret = -EINVAL; in stmfx_chip_init()
370 ret = regmap_bulk_read(stmfx->map, STMFX_REG_FW_VERSION_MSB, in stmfx_chip_init()
373 dev_err(&client->dev, "Error reading FW version: %d\n", ret); in stmfx_chip_init()
377 dev_info(&client->dev, "STMFX id: %#x, fw version: %x.%02x\n", in stmfx_chip_init()
380 ret = stmfx_chip_reset(stmfx); in stmfx_chip_init()
382 dev_err(&client->dev, "Failed to reset chip: %d\n", ret); in stmfx_chip_init()
389 if (stmfx->vdd) in stmfx_chip_init()
390 return regulator_disable(stmfx->vdd); in stmfx_chip_init()
397 struct stmfx *stmfx = i2c_get_clientdata(client); in stmfx_chip_exit() local
399 regmap_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, 0); in stmfx_chip_exit()
400 regmap_write(stmfx->map, STMFX_REG_SYS_CTRL, 0); in stmfx_chip_exit()
402 if (stmfx->vdd) { in stmfx_chip_exit()
405 ret = regulator_disable(stmfx->vdd); in stmfx_chip_exit()
407 dev_err(&client->dev, in stmfx_chip_exit()
416 struct device *dev = &client->dev; in stmfx_probe()
417 struct stmfx *stmfx; in stmfx_probe() local
420 stmfx = devm_kzalloc(dev, sizeof(*stmfx), GFP_KERNEL); in stmfx_probe()
421 if (!stmfx) in stmfx_probe()
422 return -ENOMEM; in stmfx_probe()
424 i2c_set_clientdata(client, stmfx); in stmfx_probe()
426 stmfx->dev = dev; in stmfx_probe()
428 stmfx->map = devm_regmap_init_i2c(client, &stmfx_regmap_config); in stmfx_probe()
429 if (IS_ERR(stmfx->map)) { in stmfx_probe()
430 ret = PTR_ERR(stmfx->map); in stmfx_probe()
435 mutex_init(&stmfx->lock); in stmfx_probe()
439 if (ret == -ETIMEDOUT) in stmfx_probe()
440 return -EPROBE_DEFER; in stmfx_probe()
444 if (client->irq < 0) { in stmfx_probe()
445 dev_err(dev, "Failed to get IRQ: %d\n", client->irq); in stmfx_probe()
446 ret = client->irq; in stmfx_probe()
456 0, stmfx->irq_domain); in stmfx_probe()
480 struct stmfx *stmfx = dev_get_drvdata(dev); in stmfx_suspend() local
483 ret = regmap_raw_read(stmfx->map, STMFX_REG_SYS_CTRL, in stmfx_suspend()
484 &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); in stmfx_suspend()
488 ret = regmap_raw_read(stmfx->map, STMFX_REG_IRQ_OUT_PIN, in stmfx_suspend()
489 &stmfx->bkp_irqoutpin, in stmfx_suspend()
490 sizeof(stmfx->bkp_irqoutpin)); in stmfx_suspend()
494 disable_irq(stmfx->irq); in stmfx_suspend()
496 if (stmfx->vdd) in stmfx_suspend()
497 return regulator_disable(stmfx->vdd); in stmfx_suspend()
504 struct stmfx *stmfx = dev_get_drvdata(dev); in stmfx_resume() local
507 if (stmfx->vdd) { in stmfx_resume()
508 ret = regulator_enable(stmfx->vdd); in stmfx_resume()
510 dev_err(stmfx->dev, in stmfx_resume()
516 /* Reset STMFX - supply has been stopped during suspend */ in stmfx_resume()
517 ret = stmfx_chip_reset(stmfx); in stmfx_resume()
519 dev_err(stmfx->dev, "Failed to reset chip: %d\n", ret); in stmfx_resume()
523 ret = regmap_raw_write(stmfx->map, STMFX_REG_SYS_CTRL, in stmfx_resume()
524 &stmfx->bkp_sysctrl, sizeof(stmfx->bkp_sysctrl)); in stmfx_resume()
528 ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_OUT_PIN, in stmfx_resume()
529 &stmfx->bkp_irqoutpin, in stmfx_resume()
530 sizeof(stmfx->bkp_irqoutpin)); in stmfx_resume()
534 ret = regmap_raw_write(stmfx->map, STMFX_REG_IRQ_SRC_EN, in stmfx_resume()
535 &stmfx->irq_src, sizeof(stmfx->irq_src)); in stmfx_resume()
539 enable_irq(stmfx->irq); in stmfx_resume()
548 { .compatible = "st,stmfx-0300", },
555 .name = "stmfx-core",
564 MODULE_DESCRIPTION("STMFX core driver");