diff options
Diffstat (limited to 'drivers/thermal')
-rw-r--r-- | drivers/thermal/Kconfig | 12 | ||||
-rw-r--r-- | drivers/thermal/rcar_thermal.c | 3 | ||||
-rw-r--r-- | drivers/thermal/rockchip_thermal.c | 239 | ||||
-rw-r--r-- | drivers/thermal/samsung/Kconfig | 1 | ||||
-rw-r--r-- | drivers/thermal/samsung/exynos_tmu.c | 19 | ||||
-rw-r--r-- | drivers/thermal/tegra_soctherm.c | 2 | ||||
-rw-r--r-- | drivers/thermal/ti-soc-thermal/ti-bandgap.c | 10 |
7 files changed, 171 insertions, 115 deletions
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 462d0149460d..c37eedc35a24 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -178,6 +178,7 @@ config THERMAL_EMULATION config HISI_THERMAL tristate "Hisilicon thermal driver" depends on (ARCH_HISI && CPU_THERMAL && OF) || COMPILE_TEST + depends on HAS_IOMEM help Enable this to plug hisilicon's thermal sensor driver into the Linux thermal framework. cpufreq is used as the cooling device to throttle @@ -197,6 +198,7 @@ config IMX_THERMAL config SPEAR_THERMAL tristate "SPEAr thermal sensor driver" depends on PLAT_SPEAR || COMPILE_TEST + depends on HAS_IOMEM depends on OF help Enable this to plug the SPEAr thermal sensor driver into the Linux @@ -206,6 +208,7 @@ config ROCKCHIP_THERMAL tristate "Rockchip thermal driver" depends on ARCH_ROCKCHIP || COMPILE_TEST depends on RESET_CONTROLLER + depends on HAS_IOMEM help Rockchip thermal driver provides support for Temperature sensor ADC (TS-ADC) found on Rockchip SoCs. It supports one critical @@ -214,7 +217,7 @@ config ROCKCHIP_THERMAL config RCAR_THERMAL tristate "Renesas R-Car thermal driver" - depends on ARCH_SHMOBILE || COMPILE_TEST + depends on ARCH_RENESAS || COMPILE_TEST depends on HAS_IOMEM help Enable this to plug the R-Car thermal sensor driver into the Linux @@ -223,6 +226,7 @@ config RCAR_THERMAL config KIRKWOOD_THERMAL tristate "Temperature sensor on Marvell Kirkwood SoCs" depends on MACH_KIRKWOOD || COMPILE_TEST + depends on HAS_IOMEM depends on OF help Support for the Kirkwood thermal sensor driver into the Linux thermal @@ -231,6 +235,7 @@ config KIRKWOOD_THERMAL config DOVE_THERMAL tristate "Temperature sensor on Marvell Dove SoCs" depends on ARCH_DOVE || MACH_DOVE || COMPILE_TEST + depends on HAS_IOMEM depends on OF help Support for the Dove thermal sensor driver in the Linux thermal @@ -249,6 +254,7 @@ config DB8500_THERMAL config ARMADA_THERMAL tristate "Armada 370/XP thermal management" depends on ARCH_MVEBU || COMPILE_TEST + depends on HAS_IOMEM depends on OF help Enable this option if you want to have support for thermal management @@ -266,7 +272,8 @@ config TEGRA_SOCTHERM config DB8500_CPUFREQ_COOLING tristate "DB8500 cpufreq cooling" - depends on ARCH_U8500 + depends on ARCH_U8500 || COMPILE_TEST + depends on HAS_IOMEM depends on CPU_THERMAL default y help @@ -376,6 +383,7 @@ config MTK_THERMAL menu "Texas Instruments thermal drivers" depends on ARCH_HAS_BANDGAP || COMPILE_TEST +depends on HAS_IOMEM source "drivers/thermal/ti-soc-thermal/Kconfig" endmenu diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 0e735acea33a..82daba09e150 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c @@ -430,8 +430,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) struct rcar_thermal_priv *priv; struct device *dev = &pdev->dev; struct resource *res, *irq; - const struct of_device_id *of_id = of_match_device(rcar_thermal_dt_ids, dev); - unsigned long of_data = (unsigned long)of_id->data; + unsigned long of_data = (unsigned long)of_device_get_match_data(dev); int mres = 0; int i; int ret = -ENODEV; diff --git a/drivers/thermal/rockchip_thermal.c b/drivers/thermal/rockchip_thermal.c index b58e3fb9b311..233a564442a0 100644 --- a/drivers/thermal/rockchip_thermal.c +++ b/drivers/thermal/rockchip_thermal.c @@ -58,8 +58,8 @@ enum sensor_id { /** * The conversion table has the adc value and temperature. - * ADC_DECREMENT: the adc value is of diminishing.(e.g. v2_code_table) - * ADC_INCREMENT: the adc value is incremental.(e.g. v3_code_table) + * ADC_DECREMENT: the adc value is of diminishing.(e.g. rk3288_code_table) + * ADC_INCREMENT: the adc value is incremental.(e.g. rk3368_code_table) */ enum adc_sort_mode { ADC_DECREMENT = 0, @@ -135,7 +135,13 @@ struct rockchip_thermal_data { enum tshut_polarity tshut_polarity; }; -/* TSADC Sensor info define: */ +/** + * TSADC Sensor Register description: + * + * TSADCV2_* are used for RK3288 SoCs, the other chips can reuse it. + * TSADCV3_* are used for newer SoCs than RK3288. (e.g: RK3228, RK3399) + * + */ #define TSADCV2_AUTO_CON 0x04 #define TSADCV2_INT_EN 0x08 #define TSADCV2_INT_PD 0x0c @@ -149,13 +155,20 @@ struct rockchip_thermal_data { #define TSADCV2_AUTO_EN BIT(0) #define TSADCV2_AUTO_SRC_EN(chn) BIT(4 + (chn)) #define TSADCV2_AUTO_TSHUT_POLARITY_HIGH BIT(8) +/** + * TSADCV1_AUTO_Q_SEL_EN: + * whether select (1024 - tsadc_q) as output + * 1'b0:use tsadc_q as output(temperature-code is rising sequence) + * 1'b1:use(1024 - tsadc_q) as output (temperature-code is falling sequence) + */ +#define TSADCV3_AUTO_Q_SEL_EN BIT(1) #define TSADCV2_INT_SRC_EN(chn) BIT(chn) #define TSADCV2_SHUT_2GPIO_SRC_EN(chn) BIT(4 + (chn)) #define TSADCV2_SHUT_2CRU_SRC_EN(chn) BIT(8 + (chn)) -#define TSADCV1_INT_PD_CLEAR_MASK ~BIT(16) #define TSADCV2_INT_PD_CLEAR_MASK ~BIT(8) +#define TSADCV3_INT_PD_CLEAR_MASK ~BIT(16) #define TSADCV2_DATA_MASK 0xfff #define TSADCV3_DATA_MASK 0x3ff @@ -177,45 +190,46 @@ struct tsadc_table { * linearly interpolated. * Code to Temperature mapping should be updated based on sillcon results. */ -static const struct tsadc_table v1_code_table[] = { - {TSADCV3_DATA_MASK, -40000}, - {436, -40000}, - {431, -35000}, - {426, -30000}, - {421, -25000}, - {416, -20000}, - {411, -15000}, - {406, -10000}, - {401, -5000}, - {395, 0}, - {390, 5000}, - {385, 10000}, - {380, 15000}, - {375, 20000}, - {370, 25000}, - {364, 30000}, - {359, 35000}, - {354, 40000}, - {349, 45000}, - {343, 50000}, - {338, 55000}, - {333, 60000}, - {328, 65000}, - {322, 70000}, - {317, 75000}, - {312, 80000}, - {307, 85000}, - {301, 90000}, - {296, 95000}, - {291, 100000}, - {286, 105000}, - {280, 110000}, - {275, 115000}, - {270, 120000}, - {264, 125000}, +static const struct tsadc_table rk3228_code_table[] = { + {0, -40000}, + {588, -40000}, + {593, -35000}, + {598, -30000}, + {603, -25000}, + {608, -20000}, + {613, -15000}, + {618, -10000}, + {623, -5000}, + {629, 0}, + {634, 5000}, + {639, 10000}, + {644, 15000}, + {649, 20000}, + {654, 25000}, + {660, 30000}, + {665, 35000}, + {670, 40000}, + {675, 45000}, + {681, 50000}, + {686, 55000}, + {691, 60000}, + {696, 65000}, + {702, 70000}, + {707, 75000}, + {712, 80000}, + {717, 85000}, + {723, 90000}, + {728, 95000}, + {733, 100000}, + {738, 105000}, + {744, 110000}, + {749, 115000}, + {754, 120000}, + {760, 125000}, + {TSADCV2_DATA_MASK, 125000}, }; -static const struct tsadc_table v2_code_table[] = { +static const struct tsadc_table rk3288_code_table[] = { {TSADCV2_DATA_MASK, -40000}, {3800, -40000}, {3792, -35000}, @@ -253,7 +267,7 @@ static const struct tsadc_table v2_code_table[] = { {3421, 125000}, }; -static const struct tsadc_table v3_code_table[] = { +static const struct tsadc_table rk3368_code_table[] = { {0, -40000}, {106, -40000}, {108, -35000}, @@ -292,42 +306,43 @@ static const struct tsadc_table v3_code_table[] = { {TSADCV3_DATA_MASK, 125000}, }; -static const struct tsadc_table v4_code_table[] = { - {TSADCV3_DATA_MASK, -40000}, - {431, -40000}, - {426, -35000}, - {421, -30000}, - {415, -25000}, - {410, -20000}, - {405, -15000}, - {399, -10000}, - {394, -5000}, - {389, 0}, - {383, 5000}, - {378, 10000}, - {373, 15000}, - {367, 20000}, - {362, 25000}, - {357, 30000}, - {351, 35000}, - {346, 40000}, - {340, 45000}, - {335, 50000}, - {330, 55000}, - {324, 60000}, - {319, 65000}, - {313, 70000}, - {308, 75000}, - {302, 80000}, - {297, 85000}, - {291, 90000}, - {286, 95000}, - {281, 100000}, - {275, 105000}, - {270, 110000}, - {264, 115000}, - {259, 120000}, - {253, 125000}, +static const struct tsadc_table rk3399_code_table[] = { + {0, -40000}, + {593, -40000}, + {598, -35000}, + {603, -30000}, + {609, -25000}, + {614, -20000}, + {619, -15000}, + {625, -10000}, + {630, -5000}, + {635, 0}, + {641, 5000}, + {646, 10000}, + {651, 15000}, + {657, 20000}, + {662, 25000}, + {667, 30000}, + {673, 35000}, + {678, 40000}, + {684, 45000}, + {689, 50000}, + {694, 55000}, + {700, 60000}, + {705, 65000}, + {711, 70000}, + {716, 75000}, + {722, 80000}, + {727, 85000}, + {733, 90000}, + {738, 95000}, + {743, 100000}, + {749, 105000}, + {754, 110000}, + {760, 115000}, + {765, 120000}, + {771, 125000}, + {TSADCV3_DATA_MASK, 125000}, }; static u32 rk_tsadcv2_temp_to_code(struct chip_tsadc_table table, @@ -411,7 +426,7 @@ static int rk_tsadcv2_code_to_temp(struct chip_tsadc_table table, u32 code, * temperature between 2 table entries is linear and interpolate * to produce less granular result. */ - num = table.id[mid].temp - v2_code_table[mid - 1].temp; + num = table.id[mid].temp - table.id[mid - 1].temp; num *= abs(table.id[mid - 1].code - code); denom = abs(table.id[mid - 1].code - table.id[mid].code); *temp = table.id[mid - 1].temp + (num / denom); @@ -453,20 +468,20 @@ static void rk_tsadcv2_initialize(void __iomem *regs, regs + TSADCV2_HIGHT_TSHUT_DEBOUNCE); } -static void rk_tsadcv1_irq_ack(void __iomem *regs) +static void rk_tsadcv2_irq_ack(void __iomem *regs) { u32 val; val = readl_relaxed(regs + TSADCV2_INT_PD); - writel_relaxed(val & TSADCV1_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); + writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); } -static void rk_tsadcv2_irq_ack(void __iomem *regs) +static void rk_tsadcv3_irq_ack(void __iomem *regs) { u32 val; val = readl_relaxed(regs + TSADCV2_INT_PD); - writel_relaxed(val & TSADCV2_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); + writel_relaxed(val & TSADCV3_INT_PD_CLEAR_MASK, regs + TSADCV2_INT_PD); } static void rk_tsadcv2_control(void __iomem *regs, bool enable) @@ -482,6 +497,25 @@ static void rk_tsadcv2_control(void __iomem *regs, bool enable) writel_relaxed(val, regs + TSADCV2_AUTO_CON); } +/** + * @rk_tsadcv3_control: + * TSADC controller works at auto mode, and some SoCs need set the tsadc_q_sel + * bit on TSADCV2_AUTO_CON[1]. The (1024 - tsadc_q) as output adc value if + * setting this bit to enable. + */ +static void rk_tsadcv3_control(void __iomem *regs, bool enable) +{ + u32 val; + + val = readl_relaxed(regs + TSADCV2_AUTO_CON); + if (enable) + val |= TSADCV2_AUTO_EN | TSADCV3_AUTO_Q_SEL_EN; + else + val &= ~TSADCV2_AUTO_EN; + + writel_relaxed(val, regs + TSADCV2_AUTO_CON); +} + static int rk_tsadcv2_get_temp(struct chip_tsadc_table table, int chn, void __iomem *regs, int *temp) { @@ -531,17 +565,17 @@ static const struct rockchip_tsadc_chip rk3228_tsadc_data = { .tshut_temp = 95000, .initialize = rk_tsadcv2_initialize, - .irq_ack = rk_tsadcv1_irq_ack, - .control = rk_tsadcv2_control, + .irq_ack = rk_tsadcv3_irq_ack, + .control = rk_tsadcv3_control, .get_temp = rk_tsadcv2_get_temp, .set_tshut_temp = rk_tsadcv2_tshut_temp, .set_tshut_mode = rk_tsadcv2_tshut_mode, .table = { - .id = v1_code_table, - .length = ARRAY_SIZE(v1_code_table), + .id = rk3228_code_table, + .length = ARRAY_SIZE(rk3228_code_table), .data_mask = TSADCV3_DATA_MASK, - .mode = ADC_DECREMENT, + .mode = ADC_INCREMENT, }, }; @@ -562,8 +596,8 @@ static const struct rockchip_tsadc_chip rk3288_tsadc_data = { .set_tshut_mode = rk_tsadcv2_tshut_mode, .table = { - .id = v2_code_table, - .length = ARRAY_SIZE(v2_code_table), + .id = rk3288_code_table, + .length = ARRAY_SIZE(rk3288_code_table), .data_mask = TSADCV2_DATA_MASK, .mode = ADC_DECREMENT, }, @@ -586,8 +620,8 @@ static const struct rockchip_tsadc_chip rk3368_tsadc_data = { .set_tshut_mode = rk_tsadcv2_tshut_mode, .table = { - .id = v3_code_table, - .length = ARRAY_SIZE(v3_code_table), + .id = rk3368_code_table, + .length = ARRAY_SIZE(rk3368_code_table), .data_mask = TSADCV3_DATA_MASK, .mode = ADC_INCREMENT, }, @@ -603,17 +637,17 @@ static const struct rockchip_tsadc_chip rk3399_tsadc_data = { .tshut_temp = 95000, .initialize = rk_tsadcv2_initialize, - .irq_ack = rk_tsadcv1_irq_ack, - .control = rk_tsadcv2_control, + .irq_ack = rk_tsadcv3_irq_ack, + .control = rk_tsadcv3_control, .get_temp = rk_tsadcv2_get_temp, .set_tshut_temp = rk_tsadcv2_tshut_temp, .set_tshut_mode = rk_tsadcv2_tshut_mode, .table = { - .id = v4_code_table, - .length = ARRAY_SIZE(v4_code_table), + .id = rk3399_code_table, + .length = ARRAY_SIZE(rk3399_code_table), .data_mask = TSADCV3_DATA_MASK, - .mode = ADC_DECREMENT, + .mode = ADC_INCREMENT, }, }; @@ -693,15 +727,14 @@ static int rockchip_configure_from_dt(struct device *dev, thermal->chip->tshut_temp); thermal->tshut_temp = thermal->chip->tshut_temp; } else { + if (shut_temp > INT_MAX) { + dev_err(dev, "Invalid tshut temperature specified: %d\n", + shut_temp); + return -ERANGE; + } thermal->tshut_temp = shut_temp; } - if (thermal->tshut_temp > INT_MAX) { - dev_err(dev, "Invalid tshut temperature specified: %d\n", - thermal->tshut_temp); - return -ERANGE; - } - if (of_property_read_u32(np, "rockchip,hw-tshut-mode", &tshut_mode)) { dev_warn(dev, "Missing tshut mode property, using default (%s)\n", diff --git a/drivers/thermal/samsung/Kconfig b/drivers/thermal/samsung/Kconfig index e0da3865e060..222e644169f0 100644 --- a/drivers/thermal/samsung/Kconfig +++ b/drivers/thermal/samsung/Kconfig @@ -1,6 +1,7 @@ config EXYNOS_THERMAL tristate "Exynos thermal management unit driver" depends on THERMAL_OF + depends on HAS_IOMEM help If you say yes here you get support for the TMU (Thermal Management Unit) driver for SAMSUNG EXYNOS series of SoCs. This driver initialises diff --git a/drivers/thermal/samsung/exynos_tmu.c b/drivers/thermal/samsung/exynos_tmu.c index fa61eff88496..f3ce94ec73b5 100644 --- a/drivers/thermal/samsung/exynos_tmu.c +++ b/drivers/thermal/samsung/exynos_tmu.c @@ -184,6 +184,7 @@ * @temp_error2: fused value of the second point trim. * @regulator: pointer to the TMU regulator structure. * @reg_conf: pointer to structure to register with core thermal. + * @ntrip: number of supported trip points. * @tmu_initialize: SoC specific TMU initialization method * @tmu_control: SoC specific TMU control method * @tmu_read: SoC specific TMU temperature read method @@ -203,6 +204,7 @@ struct exynos_tmu_data { u16 temp_error1, temp_error2; struct regulator *regulator; struct thermal_zone_device *tzd; + unsigned int ntrip; int (*tmu_initialize)(struct platform_device *pdev); void (*tmu_control)(struct platform_device *pdev, bool on); @@ -346,6 +348,14 @@ static int exynos_tmu_initialize(struct platform_device *pdev) struct exynos_tmu_data *data = platform_get_drvdata(pdev); int ret; + if (of_thermal_get_ntrips(data->tzd) > data->ntrip) { + dev_info(&pdev->dev, + "More trip points than supported by this TMU.\n"); + dev_info(&pdev->dev, + "%d trip points should be configured in polling mode.\n", + (of_thermal_get_ntrips(data->tzd) - data->ntrip)); + } + mutex_lock(&data->lock); clk_enable(data->clk); if (!IS_ERR(data->clk_sec)) @@ -1210,6 +1220,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_control = exynos4210_tmu_control; data->tmu_read = exynos4210_tmu_read; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; + data->ntrip = 4; break; case SOC_ARCH_EXYNOS3250: case SOC_ARCH_EXYNOS4412: @@ -1222,6 +1233,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos4412_tmu_read; data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; + data->ntrip = 4; break; case SOC_ARCH_EXYNOS5433: data->tmu_initialize = exynos5433_tmu_initialize; @@ -1229,6 +1241,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos4412_tmu_read; data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; + data->ntrip = 8; break; case SOC_ARCH_EXYNOS5440: data->tmu_initialize = exynos5440_tmu_initialize; @@ -1236,6 +1249,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos5440_tmu_read; data->tmu_set_emulation = exynos5440_tmu_set_emulation; data->tmu_clear_irqs = exynos5440_tmu_clear_irqs; + data->ntrip = 4; break; case SOC_ARCH_EXYNOS7: data->tmu_initialize = exynos7_tmu_initialize; @@ -1243,6 +1257,7 @@ static int exynos_map_dt_data(struct platform_device *pdev) data->tmu_read = exynos7_tmu_read; data->tmu_set_emulation = exynos4412_tmu_set_emulation; data->tmu_clear_irqs = exynos4210_tmu_clear_irqs; + data->ntrip = 8; break; default: dev_err(&pdev->dev, "Platform not supported\n"); @@ -1295,7 +1310,7 @@ static int exynos_tmu_probe(struct platform_device *pdev) * TODO: Add regulator as an SOC feature, so that regulator enable * is a compulsory call. */ - data->regulator = devm_regulator_get(&pdev->dev, "vtmu"); + data->regulator = devm_regulator_get_optional(&pdev->dev, "vtmu"); if (!IS_ERR(data->regulator)) { ret = regulator_enable(data->regulator); if (ret) { @@ -1303,6 +1318,8 @@ static int exynos_tmu_probe(struct platform_device *pdev) return ret; } } else { + if (PTR_ERR(data->regulator) == -EPROBE_DEFER) + return -EPROBE_DEFER; dev_info(&pdev->dev, "Regulator node (vtmu) not found\n"); } diff --git a/drivers/thermal/tegra_soctherm.c b/drivers/thermal/tegra_soctherm.c index 74ea5765938b..136975220c92 100644 --- a/drivers/thermal/tegra_soctherm.c +++ b/drivers/thermal/tegra_soctherm.c @@ -57,7 +57,7 @@ #define READBACK_VALUE_MASK 0xff00 #define READBACK_VALUE_SHIFT 8 #define READBACK_ADD_HALF BIT(7) -#define READBACK_NEGATE BIT(1) +#define READBACK_NEGATE BIT(0) #define FUSE_TSENSOR8_CALIB 0x180 #define FUSE_SPARE_REALIGNMENT_REG_0 0x1fc diff --git a/drivers/thermal/ti-soc-thermal/ti-bandgap.c b/drivers/thermal/ti-soc-thermal/ti-bandgap.c index 1e34a1efc554..06ea9766a70a 100644 --- a/drivers/thermal/ti-soc-thermal/ti-bandgap.c +++ b/drivers/thermal/ti-soc-thermal/ti-bandgap.c @@ -1265,7 +1265,7 @@ static int ti_bandgap_probe(struct platform_device *pdev) { struct ti_bandgap *bgp; - int clk_rate, ret = 0, i; + int clk_rate, ret, i; bgp = ti_bandgap_build(pdev); if (IS_ERR(bgp)) { @@ -1288,16 +1288,14 @@ int ti_bandgap_probe(struct platform_device *pdev) } bgp->fclock = clk_get(NULL, bgp->conf->fclock_name); - ret = IS_ERR(bgp->fclock); - if (ret) { + if (IS_ERR(bgp->fclock)) { dev_err(&pdev->dev, "failed to request fclock reference\n"); ret = PTR_ERR(bgp->fclock); goto free_irqs; } bgp->div_clk = clk_get(NULL, bgp->conf->div_ck_name); - ret = IS_ERR(bgp->div_clk); - if (ret) { + if (IS_ERR(bgp->div_clk)) { dev_err(&pdev->dev, "failed to request div_ts_ck clock ref\n"); ret = PTR_ERR(bgp->div_clk); goto free_irqs; @@ -1314,7 +1312,7 @@ int ti_bandgap_probe(struct platform_device *pdev) * may not be accurate */ val = ti_bandgap_readl(bgp, tsr->bgap_efuse); - if (ret || !val) + if (!val) dev_info(&pdev->dev, "Non-trimmed BGAP, Temp not accurate\n"); } |