aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPuneet Saxena <puneets@nvidia.com>2011-05-04 01:04:10 -0400
committerHerbert Xu <herbert@gondor.apana.org.au>2011-05-04 01:04:10 -0400
commitba0e14acc417eceb895efda1ff46366f4d1728f8 (patch)
treed2deee9515bf47356967053179bf678a586eab47
parentec8e8dfe5f862a01bf1b5cdac441c083ce0a2a22 (diff)
crypto: testmgr - add support for aes ofb mode
the fix add testcase for testing aes ofb mode. Signed-off-by: Puneet Saxena <puneets@nvidia.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--crypto/testmgr.c16
-rw-r--r--crypto/testmgr.h60
2 files changed, 76 insertions, 0 deletions
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 2854865f2434..b6b93d416351 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -2219,6 +2219,22 @@ static const struct alg_test_desc alg_test_descs[] = {
2219 } 2219 }
2220 } 2220 }
2221 }, { 2221 }, {
2222 .alg = "ofb(aes)",
2223 .test = alg_test_skcipher,
2224 .fips_allowed = 1,
2225 .suite = {
2226 .cipher = {
2227 .enc = {
2228 .vecs = aes_ofb_enc_tv_template,
2229 .count = AES_OFB_ENC_TEST_VECTORS
2230 },
2231 .dec = {
2232 .vecs = aes_ofb_dec_tv_template,
2233 .count = AES_OFB_DEC_TEST_VECTORS
2234 }
2235 }
2236 }
2237 }, {
2222 .alg = "pcbc(fcrypt)", 2238 .alg = "pcbc(fcrypt)",
2223 .test = alg_test_skcipher, 2239 .test = alg_test_skcipher,
2224 .suite = { 2240 .suite = {
diff --git a/crypto/testmgr.h b/crypto/testmgr.h
index aa6dac05f843..27e60619538e 100644
--- a/crypto/testmgr.h
+++ b/crypto/testmgr.h
@@ -2980,6 +2980,8 @@ static struct cipher_testvec cast6_dec_tv_template[] = {
2980#define AES_XTS_DEC_TEST_VECTORS 4 2980#define AES_XTS_DEC_TEST_VECTORS 4
2981#define AES_CTR_ENC_TEST_VECTORS 3 2981#define AES_CTR_ENC_TEST_VECTORS 3
2982#define AES_CTR_DEC_TEST_VECTORS 3 2982#define AES_CTR_DEC_TEST_VECTORS 3
2983#define AES_OFB_ENC_TEST_VECTORS 1
2984#define AES_OFB_DEC_TEST_VECTORS 1
2983#define AES_CTR_3686_ENC_TEST_VECTORS 7 2985#define AES_CTR_3686_ENC_TEST_VECTORS 7
2984#define AES_CTR_3686_DEC_TEST_VECTORS 6 2986#define AES_CTR_3686_DEC_TEST_VECTORS 6
2985#define AES_GCM_ENC_TEST_VECTORS 9 2987#define AES_GCM_ENC_TEST_VECTORS 9
@@ -5506,6 +5508,64 @@ static struct cipher_testvec aes_ctr_rfc3686_dec_tv_template[] = {
5506 }, 5508 },
5507}; 5509};
5508 5510
5511static struct cipher_testvec aes_ofb_enc_tv_template[] = {
5512 /* From NIST Special Publication 800-38A, Appendix F.5 */
5513 {
5514 .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
5515 "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
5516 .klen = 16,
5517 .iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08"
5518 "\x09\x0a\x0b\x0c\x0d\x0e\x0f",
5519 .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
5520 "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
5521 "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
5522 "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
5523 "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
5524 "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
5525 "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
5526 "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
5527 .ilen = 64,
5528 .result = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20"
5529 "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a"
5530 "\x77\x89\x50\x8d\x16\x91\x8f\x03\xf5"
5531 "\x3c\x52\xda\xc5\x4e\xd8\x25"
5532 "\x97\x40\x05\x1e\x9c\x5f\xec\xf6\x43"
5533 "\x44\xf7\xa8\x22\x60\xed\xcc"
5534 "\x30\x4c\x65\x28\xf6\x59\xc7\x78"
5535 "\x66\xa5\x10\xd9\xc1\xd6\xae\x5e",
5536 .rlen = 64,
5537 }
5538};
5539
5540static struct cipher_testvec aes_ofb_dec_tv_template[] = {
5541 /* From NIST Special Publication 800-38A, Appendix F.5 */
5542 {
5543 .key = "\x2b\x7e\x15\x16\x28\xae\xd2\xa6"
5544 "\xab\xf7\x15\x88\x09\xcf\x4f\x3c",
5545 .klen = 16,
5546 .iv = "\x00\x01\x02\x03\x04\x05\x06\x07\x08"
5547 "\x09\x0a\x0b\x0c\x0d\x0e\x0f",
5548 .input = "\x3b\x3f\xd9\x2e\xb7\x2d\xad\x20"
5549 "\x33\x34\x49\xf8\xe8\x3c\xfb\x4a"
5550 "\x77\x89\x50\x8d\x16\x91\x8f\x03\xf5"
5551 "\x3c\x52\xda\xc5\x4e\xd8\x25"
5552 "\x97\x40\x05\x1e\x9c\x5f\xec\xf6\x43"
5553 "\x44\xf7\xa8\x22\x60\xed\xcc"
5554 "\x30\x4c\x65\x28\xf6\x59\xc7\x78"
5555 "\x66\xa5\x10\xd9\xc1\xd6\xae\x5e",
5556 .ilen = 64,
5557 .result = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
5558 "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
5559 "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
5560 "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
5561 "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
5562 "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
5563 "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
5564 "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
5565 .rlen = 64,
5566 }
5567};
5568
5509static struct aead_testvec aes_gcm_enc_tv_template[] = { 5569static struct aead_testvec aes_gcm_enc_tv_template[] = {
5510 { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */ 5570 { /* From McGrew & Viega - http://citeseer.ist.psu.edu/656989.html */
5511 .key = zeroed_string, 5571 .key = zeroed_string,
= TPS65917_INT4_STATUS_GPIO_4, .reg_offset = 3, }, [TPS65917_GPIO_5_IRQ] = { .mask = TPS65917_INT4_STATUS_GPIO_5, .reg_offset = 3, }, [TPS65917_GPIO_6_IRQ] = { .mask = TPS65917_INT4_STATUS_GPIO_6, .reg_offset = 3, }, [TPS65917_RESERVED10] = { .mask = TPS65917_RESERVED10, .reg_offset = 3, }, }; static const struct regmap_irq palmas_irqs[] = { /* INT1 IRQs */ [PALMAS_CHARG_DET_N_VBUS_OVV_IRQ] = { .mask = PALMAS_INT1_STATUS_CHARG_DET_N_VBUS_OVV, }, [PALMAS_PWRON_IRQ] = { .mask = PALMAS_INT1_STATUS_PWRON, }, [PALMAS_LONG_PRESS_KEY_IRQ] = { .mask = PALMAS_INT1_STATUS_LONG_PRESS_KEY, }, [PALMAS_RPWRON_IRQ] = { .mask = PALMAS_INT1_STATUS_RPWRON, }, [PALMAS_PWRDOWN_IRQ] = { .mask = PALMAS_INT1_STATUS_PWRDOWN, }, [PALMAS_HOTDIE_IRQ] = { .mask = PALMAS_INT1_STATUS_HOTDIE, }, [PALMAS_VSYS_MON_IRQ] = { .mask = PALMAS_INT1_STATUS_VSYS_MON, }, [PALMAS_VBAT_MON_IRQ] = { .mask = PALMAS_INT1_STATUS_VBAT_MON, }, /* INT2 IRQs*/ [PALMAS_RTC_ALARM_IRQ] = { .mask = PALMAS_INT2_STATUS_RTC_ALARM, .reg_offset = 1, }, [PALMAS_RTC_TIMER_IRQ] = { .mask = PALMAS_INT2_STATUS_RTC_TIMER, .reg_offset = 1, }, [PALMAS_WDT_IRQ] = { .mask = PALMAS_INT2_STATUS_WDT, .reg_offset = 1, }, [PALMAS_BATREMOVAL_IRQ] = { .mask = PALMAS_INT2_STATUS_BATREMOVAL, .reg_offset = 1, }, [PALMAS_RESET_IN_IRQ] = { .mask = PALMAS_INT2_STATUS_RESET_IN, .reg_offset = 1, }, [PALMAS_FBI_BB_IRQ] = { .mask = PALMAS_INT2_STATUS_FBI_BB, .reg_offset = 1, }, [PALMAS_SHORT_IRQ] = { .mask = PALMAS_INT2_STATUS_SHORT, .reg_offset = 1, }, [PALMAS_VAC_ACOK_IRQ] = { .mask = PALMAS_INT2_STATUS_VAC_ACOK, .reg_offset = 1, }, /* INT3 IRQs */ [PALMAS_GPADC_AUTO_0_IRQ] = { .mask = PALMAS_INT3_STATUS_GPADC_AUTO_0, .reg_offset = 2, }, [PALMAS_GPADC_AUTO_1_IRQ] = { .mask = PALMAS_INT3_STATUS_GPADC_AUTO_1, .reg_offset = 2, }, [PALMAS_GPADC_EOC_SW_IRQ] = { .mask = PALMAS_INT3_STATUS_GPADC_EOC_SW, .reg_offset = 2, }, [PALMAS_GPADC_EOC_RT_IRQ] = { .mask = PALMAS_INT3_STATUS_GPADC_EOC_RT, .reg_offset = 2, }, [PALMAS_ID_OTG_IRQ] = { .mask = PALMAS_INT3_STATUS_ID_OTG, .reg_offset = 2, }, [PALMAS_ID_IRQ] = { .mask = PALMAS_INT3_STATUS_ID, .reg_offset = 2, }, [PALMAS_VBUS_OTG_IRQ] = { .mask = PALMAS_INT3_STATUS_VBUS_OTG, .reg_offset = 2, }, [PALMAS_VBUS_IRQ] = { .mask = PALMAS_INT3_STATUS_VBUS, .reg_offset = 2, }, /* INT4 IRQs */ [PALMAS_GPIO_0_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_0, .reg_offset = 3, }, [PALMAS_GPIO_1_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_1, .reg_offset = 3, }, [PALMAS_GPIO_2_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_2, .reg_offset = 3, }, [PALMAS_GPIO_3_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_3, .reg_offset = 3, }, [PALMAS_GPIO_4_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_4, .reg_offset = 3, }, [PALMAS_GPIO_5_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_5, .reg_offset = 3, }, [PALMAS_GPIO_6_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_6, .reg_offset = 3, }, [PALMAS_GPIO_7_IRQ] = { .mask = PALMAS_INT4_STATUS_GPIO_7, .reg_offset = 3, }, }; static struct regmap_irq_chip palmas_irq_chip = { .name = "palmas", .irqs = palmas_irqs, .num_irqs = ARRAY_SIZE(palmas_irqs), .num_regs = 4, .irq_reg_stride = 5, .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT1_STATUS), .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT1_MASK), }; static struct regmap_irq_chip tps65917_irq_chip = { .name = "tps65917", .irqs = tps65917_irqs, .num_irqs = ARRAY_SIZE(tps65917_irqs), .num_regs = 4, .irq_reg_stride = 5, .status_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT1_STATUS), .mask_base = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT1_MASK), }; int palmas_ext_control_req_config(struct palmas *palmas, enum palmas_external_requestor_id id, int ext_ctrl, bool enable) { struct palmas_pmic_driver_data *pmic_ddata = palmas->pmic_ddata; int preq_mask_bit = 0; int reg_add = 0; int bit_pos, ret; if (!(ext_ctrl & PALMAS_EXT_REQ)) return 0; if (id >= PALMAS_EXTERNAL_REQSTR_ID_MAX) return 0; if (ext_ctrl & PALMAS_EXT_CONTROL_NSLEEP) { reg_add = PALMAS_NSLEEP_RES_ASSIGN; preq_mask_bit = 0; } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE1) { reg_add = PALMAS_ENABLE1_RES_ASSIGN; preq_mask_bit = 1; } else if (ext_ctrl & PALMAS_EXT_CONTROL_ENABLE2) { reg_add = PALMAS_ENABLE2_RES_ASSIGN; preq_mask_bit = 2; } bit_pos = pmic_ddata->sleep_req_info[id].bit_pos; reg_add += pmic_ddata->sleep_req_info[id].reg_offset; if (enable) ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, reg_add, BIT(bit_pos), BIT(bit_pos)); else ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE, reg_add, BIT(bit_pos), 0); if (ret < 0) { dev_err(palmas->dev, "Resource reg 0x%02x update failed %d\n", reg_add, ret); return ret; } /* Unmask the PREQ */ ret = palmas_update_bits(palmas, PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL, BIT(preq_mask_bit), 0); if (ret < 0) { dev_err(palmas->dev, "POWER_CTRL register update failed %d\n", ret); return ret; } return ret; } EXPORT_SYMBOL_GPL(palmas_ext_control_req_config); static int palmas_set_pdata_irq_flag(struct i2c_client *i2c, struct palmas_platform_data *pdata) { struct irq_data *irq_data = irq_get_irq_data(i2c->irq); if (!irq_data) { dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq); return -EINVAL; } pdata->irq_flags = irqd_get_trigger_type(irq_data); dev_info(&i2c->dev, "Irq flag is 0x%08x\n", pdata->irq_flags); return 0; } static void palmas_dt_to_pdata(struct i2c_client *i2c, struct palmas_platform_data *pdata) { struct device_node *node = i2c->dev.of_node; int ret; u32 prop; ret = of_property_read_u32(node, "ti,mux-pad1", &prop); if (!ret) { pdata->mux_from_pdata = 1; pdata->pad1 = prop; } ret = of_property_read_u32(node, "ti,mux-pad2", &prop); if (!ret) { pdata->mux_from_pdata = 1; pdata->pad2 = prop; } /* The default for this register is all masked */ ret = of_property_read_u32(node, "ti,power-ctrl", &prop); if (!ret) pdata->power_ctrl = prop; else pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK | PALMAS_POWER_CTRL_ENABLE1_MASK | PALMAS_POWER_CTRL_ENABLE2_MASK; if (i2c->irq) palmas_set_pdata_irq_flag(i2c, pdata); pdata->pm_off = of_property_read_bool(node, "ti,system-power-controller"); } static struct palmas *palmas_dev; static void palmas_power_off(void) { unsigned int addr; int ret, slave; if (!palmas_dev) return; slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_DEV_CTRL); ret = regmap_update_bits( palmas_dev->regmap[slave], addr, PALMAS_DEV_CTRL_DEV_ON, 0); if (ret) pr_err("%s: Unable to write to DEV_CTRL_DEV_ON: %d\n", __func__, ret); } static unsigned int palmas_features = PALMAS_PMIC_FEATURE_SMPS10_BOOST; static unsigned int tps659038_features; struct palmas_driver_data { unsigned int *features; struct regmap_irq_chip *irq_chip; }; static struct palmas_driver_data palmas_data = { .features = &palmas_features, .irq_chip = &palmas_irq_chip, }; static struct palmas_driver_data tps659038_data = { .features = &tps659038_features, .irq_chip = &palmas_irq_chip, }; static struct palmas_driver_data tps65917_data = { .features = &tps659038_features, .irq_chip = &tps65917_irq_chip, }; static const struct of_device_id of_palmas_match_tbl[] = { { .compatible = "ti,palmas", .data = &palmas_data, }, { .compatible = "ti,tps659038", .data = &tps659038_data, }, { .compatible = "ti,tps65917", .data = &tps65917_data, }, { }, }; MODULE_DEVICE_TABLE(of, of_palmas_match_tbl); static int palmas_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { struct palmas *palmas; struct palmas_platform_data *pdata; struct palmas_driver_data *driver_data; struct device_node *node = i2c->dev.of_node; int ret = 0, i; unsigned int reg, addr; int slave; const struct of_device_id *match; pdata = dev_get_platdata(&i2c->dev); if (node && !pdata) { pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; palmas_dt_to_pdata(i2c, pdata); } if (!pdata) return -EINVAL; palmas = devm_kzalloc(&i2c->dev, sizeof(struct palmas), GFP_KERNEL); if (palmas == NULL) return -ENOMEM; i2c_set_clientdata(i2c, palmas); palmas->dev = &i2c->dev; palmas->irq = i2c->irq; match = of_match_device(of_palmas_match_tbl, &i2c->dev); if (!match) return -ENODATA; driver_data = (struct palmas_driver_data *)match->data; palmas->features = *driver_data->features; for (i = 0; i < PALMAS_NUM_CLIENTS; i++) { if (i == 0) palmas->i2c_clients[i] = i2c; else { palmas->i2c_clients[i] = i2c_new_dummy(i2c->adapter, i2c->addr + i); if (!palmas->i2c_clients[i]) { dev_err(palmas->dev, "can't attach client %d\n", i); ret = -ENOMEM; goto err_i2c; } palmas->i2c_clients[i]->dev.of_node = of_node_get(node); } palmas->regmap[i] = devm_regmap_init_i2c(palmas->i2c_clients[i], &palmas_regmap_config[i]); if (IS_ERR(palmas->regmap[i])) { ret = PTR_ERR(palmas->regmap[i]); dev_err(palmas->dev, "Failed to allocate regmap %d, err: %d\n", i, ret); goto err_i2c; } } if (!palmas->irq) { dev_warn(palmas->dev, "IRQ missing: skipping irq request\n"); goto no_irq; } /* Change interrupt line output polarity */ if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH) reg = PALMAS_POLARITY_CTRL_INT_POLARITY; else reg = 0; ret = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE, PALMAS_POLARITY_CTRL, PALMAS_POLARITY_CTRL_INT_POLARITY, reg); if (ret < 0) { dev_err(palmas->dev, "POLARITY_CTRL updat failed: %d\n", ret); goto err_i2c; } /* Change IRQ into clear on read mode for efficiency */ slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); reg = PALMAS_INT_CTRL_INT_CLEAR; regmap_write(palmas->regmap[slave], addr, reg); ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, IRQF_ONESHOT | pdata->irq_flags, 0, driver_data->irq_chip, &palmas->irq_data); if (ret < 0) goto err_i2c; no_irq: slave = PALMAS_BASE_TO_SLAVE(PALMAS_PU_PD_OD_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, PALMAS_PRIMARY_SECONDARY_PAD1); if (pdata->mux_from_pdata) { reg = pdata->pad1; ret = regmap_write(palmas->regmap[slave], addr, reg); if (ret) goto err_irq; } else { ret = regmap_read(palmas->regmap[slave], addr, &reg); if (ret) goto err_irq; } if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_0)) palmas->gpio_muxed |= PALMAS_GPIO_0_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK)) palmas->gpio_muxed |= PALMAS_GPIO_1_MUXED; else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) palmas->led_muxed |= PALMAS_LED1_MUXED; else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_MASK) == (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_1_SHIFT)) palmas->pwm_muxed |= PALMAS_PWM1_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK)) palmas->gpio_muxed |= PALMAS_GPIO_2_MUXED; else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == (2 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) palmas->led_muxed |= PALMAS_LED2_MUXED; else if ((reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_MASK) == (3 << PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_2_SHIFT)) palmas->pwm_muxed |= PALMAS_PWM2_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD1_GPIO_3)) palmas->gpio_muxed |= PALMAS_GPIO_3_MUXED; addr = PALMAS_BASE_TO_REG(PALMAS_PU_PD_OD_BASE, PALMAS_PRIMARY_SECONDARY_PAD2); if (pdata->mux_from_pdata) { reg = pdata->pad2; ret = regmap_write(palmas->regmap[slave], addr, reg); if (ret) goto err_irq; } else { ret = regmap_read(palmas->regmap[slave], addr, &reg); if (ret) goto err_irq; } if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_4)) palmas->gpio_muxed |= PALMAS_GPIO_4_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_5_MASK)) palmas->gpio_muxed |= PALMAS_GPIO_5_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_6)) palmas->gpio_muxed |= PALMAS_GPIO_6_MUXED; if (!(reg & PALMAS_PRIMARY_SECONDARY_PAD2_GPIO_7_MASK)) palmas->gpio_muxed |= PALMAS_GPIO_7_MUXED; dev_info(palmas->dev, "Muxing GPIO %x, PWM %x, LED %x\n", palmas->gpio_muxed, palmas->pwm_muxed, palmas->led_muxed); reg = pdata->power_ctrl; slave = PALMAS_BASE_TO_SLAVE(PALMAS_PMU_CONTROL_BASE); addr = PALMAS_BASE_TO_REG(PALMAS_PMU_CONTROL_BASE, PALMAS_POWER_CTRL); ret = regmap_write(palmas->regmap[slave], addr, reg); if (ret) goto err_irq; /* * If we are probing with DT do this the DT way and return here * otherwise continue and add devices using mfd helpers. */ if (node) { ret = of_platform_populate(node, NULL, NULL, &i2c->dev); if (ret < 0) { goto err_irq; } else if (pdata->pm_off && !pm_power_off) { palmas_dev = palmas; pm_power_off = palmas_power_off; } } return ret; err_irq: regmap_del_irq_chip(palmas->irq, palmas->irq_data); err_i2c: for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { if (palmas->i2c_clients[i]) i2c_unregister_device(palmas->i2c_clients[i]); } return ret; } static int palmas_i2c_remove(struct i2c_client *i2c) { struct palmas *palmas = i2c_get_clientdata(i2c); int i; regmap_del_irq_chip(palmas->irq, palmas->irq_data); for (i = 1; i < PALMAS_NUM_CLIENTS; i++) { if (palmas->i2c_clients[i]) i2c_unregister_device(palmas->i2c_clients[i]); } if (palmas == palmas_dev) { pm_power_off = NULL; palmas_dev = NULL; } return 0; } static const struct i2c_device_id palmas_i2c_id[] = { { "palmas", }, { "twl6035", }, { "twl6037", }, { "tps65913", }, { /* end */ } }; MODULE_DEVICE_TABLE(i2c, palmas_i2c_id); static struct i2c_driver palmas_i2c_driver = { .driver = { .name = "palmas", .of_match_table = of_palmas_match_tbl, .owner = THIS_MODULE, }, .probe = palmas_i2c_probe, .remove = palmas_i2c_remove, .id_table = palmas_i2c_id, }; static int __init palmas_i2c_init(void) { return i2c_add_driver(&palmas_i2c_driver); } /* init early so consumer devices can complete system boot */ subsys_initcall(palmas_i2c_init); static void __exit palmas_i2c_exit(void) { i2c_del_driver(&palmas_i2c_driver); } module_exit(palmas_i2c_exit); MODULE_AUTHOR("Graeme Gregory <gg@slimlogic.co.uk>"); MODULE_DESCRIPTION("Palmas chip family multi-function driver"); MODULE_LICENSE("GPL");