diff --git a/Documentation/devicetree/bindings/hwlock/rockchip-hwspinlock.txt b/Documentation/devicetree/bindings/hwlock/rockchip-hwspinlock.txt index 4ef595eaa94a..245b36e5c5bd 100644 --- a/Documentation/devicetree/bindings/hwlock/rockchip-hwspinlock.txt +++ b/Documentation/devicetree/bindings/hwlock/rockchip-hwspinlock.txt @@ -10,6 +10,9 @@ Required properties : - #hwlock-cells : hwlock users only use the hwlock id to represent a specific hwlock, so the number of cells should be <1> here. +Optional properties : +- rockchip,hwlock-user-id : Set hwlock user id (4 bit, default is 0x01). + Please look at the generic hwlock binding for usage information for consumers, "Documentation/devicetree/bindings/hwlock/hwlock.txt" diff --git a/drivers/hwspinlock/rockchip_hwspinlock.c b/drivers/hwspinlock/rockchip_hwspinlock.c index 26ba8ec31f01..94830aa54bb0 100644 --- a/drivers/hwspinlock/rockchip_hwspinlock.c +++ b/drivers/hwspinlock/rockchip_hwspinlock.c @@ -22,26 +22,37 @@ struct rockchip_hwspinlock { /* Hardware spinlock register offsets */ #define HWSPINLOCK_OFFSET(x) (0x4 * (x)) +#define HWSPINLOCK_ID_MASK 0x0F -#define HWSPINLOCK_OWNER_ID 0x01 +#define HWLOCK_DEFAULT_USER 0x01 + +static u32 hwlock_user_id; static int rockchip_hwspinlock_trylock(struct hwspinlock *lock) { void __iomem *lock_addr = lock->priv; - writel(HWSPINLOCK_OWNER_ID, lock_addr); + writel(hwlock_user_id, lock_addr); /* * Get only first 4 bits and compare to HWSPINLOCK_OWNER_ID, * if equal, we attempt to acquire the lock, otherwise, * someone else has it. */ - return (HWSPINLOCK_OWNER_ID == (0x0F & readl(lock_addr))); + return (hwlock_user_id == (readl(lock_addr) & HWSPINLOCK_ID_MASK)); } static void rockchip_hwspinlock_unlock(struct hwspinlock *lock) { void __iomem *lock_addr = lock->priv; + u32 lock_owner = readl(lock_addr) & HWSPINLOCK_ID_MASK; + + if (lock_owner != hwlock_user_id) { + dev_warn(lock->bank->dev, + "WARNING: against user %u release a lock held by %u\n", + hwlock_user_id, lock_owner); + return; + } /* Release the lock by writing 0 to it */ writel(0, lock_addr); @@ -56,7 +67,7 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev) { struct rockchip_hwspinlock *hwspin; struct hwspinlock *hwlock; - int idx; + int idx, ret; hwspin = devm_kzalloc(&pdev->dev, struct_size(hwspin, bank.lock, HWSPINLOCK_NUMBER), @@ -68,6 +79,12 @@ static int rockchip_hwspinlock_probe(struct platform_device *pdev) if (IS_ERR(hwspin->io_base)) return PTR_ERR(hwspin->io_base); + ret = device_property_read_u32(&pdev->dev, "rockchip,hwlock-user-id", + &hwlock_user_id); + if (ret || !hwlock_user_id || hwlock_user_id > HWSPINLOCK_ID_MASK) + hwlock_user_id = HWLOCK_DEFAULT_USER; + dev_info(&pdev->dev, "hwlock user id %u\n", hwlock_user_id); + for (idx = 0; idx < HWSPINLOCK_NUMBER; idx++) { hwlock = &hwspin->bank.lock[idx]; hwlock->priv = hwspin->io_base + HWSPINLOCK_OFFSET(idx); diff --git a/drivers/media/i2c/sc530ai.c b/drivers/media/i2c/sc530ai.c index adfb82c7b0f1..205e4529567d 100644 --- a/drivers/media/i2c/sc530ai.c +++ b/drivers/media/i2c/sc530ai.c @@ -80,7 +80,7 @@ #define SC530AI_REG_ANA_GAIN 0x3e09 #define SC530AI_GAIN_MIN 0x20 -#define SC530AI_GAIN_MAX (32 * 326) +#define SC530AI_GAIN_MAX (9635) //76.48 * 3.938 * 32 #define SC530AI_GAIN_STEP 1 #define SC530AI_GAIN_DEFAULT 0x20 @@ -1007,39 +1007,40 @@ static void sc530ai_get_gain_reg(u32 total_gain, u32 *again, u32 *dgain, *again = 0x00; *dgain = 0x00; *dgain_fine = gain_factor * 128 / 1000; - } else if (gain_factor < 2550) { /* 2x - 2.55x gain */ + } else if (gain_factor < 2390) { /* 2x - 2.39x gain */ *again = 0x01; *dgain = 0x00; *dgain_fine = gain_factor * 128 / 2000; - } else if (gain_factor < 2550 * 2) { /* 2.55x - 5.1x gain */ + } else if (gain_factor < 2390 * 2) { /* 2.39x - 4.78x gain */ *again = 0x40; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 2550; - } else if (gain_factor < 2550 * 4) { /* 5.1x - 10.2x gain */ + *dgain_fine = gain_factor * 128 / 2390; + } else if (gain_factor < 2390 * 4) { /* 4.78x - 9.56x gain */ *again = 0x48; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 5110; - } else if (gain_factor < 2550 * 8) { /* 10.2x - 20.4x gain */ + *dgain_fine = gain_factor * 128 / 2390 / 2; + } else if (gain_factor < 2390 * 8) { /* 9.56x - 19.12x gain */ *again = 0x49; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 10200; - } else if (gain_factor < 2550 * 16) { /* 20.4x - 40.8x gain */ + *dgain_fine = gain_factor * 128 / 2390 / 4; + } else if (gain_factor < 2390 * 16) { /* 19.12x - 38.24x gain */ *again = 0x4B; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 20400; - } else if (gain_factor < 2550 * 32) { /* 40.8x - 81.6x gain */ + *dgain_fine = gain_factor * 128 / 2390 / 8; + } else if (gain_factor < 2390 * 32) { /* 38.24x - 76.48x gain */ *again = 0x4f; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 40800; - } else if (gain_factor < 2550 * 64) { /* 81.6x - 163.2x gain */ + *dgain_fine = gain_factor * 128 / 2390 / 16; + } else if (gain_factor < 2390 * 64) { /* 76.48x - 152.96x gain */ *again = 0x5f; *dgain = 0x00; - *dgain_fine = gain_factor * 128 / 40800 / 2; - } else if (gain_factor < 2550 * 128) { /* 163.2x - 326.4x gain */ + *dgain_fine = gain_factor * 128 / 2390 / 32; + } else if (gain_factor < 2390 * 128) { /* 152.96x - 301.1x gain */ *again = 0x5f; *dgain = 0x01; - *dgain_fine = gain_factor * 128 / 40800 / 4; + *dgain_fine = gain_factor * 128 / 2390 / 64; } + *dgain_fine = *dgain_fine / 4 * 4; } static int sc530ai_set_hdrae(struct sc530ai *sc530ai,