linux/drivers/mfd/twl4030-power.c
<<
>>
Prefs
   1/*
   2 * linux/drivers/i2c/chips/twl4030-power.c
   3 *
   4 * Handle TWL4030 Power initialization
   5 *
   6 * Copyright (C) 2008 Nokia Corporation
   7 * Copyright (C) 2006 Texas Instruments, Inc
   8 *
   9 * Written by   Kalle Jokiniemi
  10 *              Peter De Schrijver <peter.de-schrijver@nokia.com>
  11 * Several fixes by Amit Kucheria <amit.kucheria@verdurent.com>
  12 *
  13 * This file is subject to the terms and conditions of the GNU General
  14 * Public License. See the file "COPYING" in the main directory of this
  15 * archive for more details.
  16 *
  17 * This program is distributed in the hope that it will be useful,
  18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20 * GNU General Public License for more details.
  21 *
  22 * You should have received a copy of the GNU General Public License
  23 * along with this program; if not, write to the Free Software
  24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  25 */
  26
  27#include <linux/module.h>
  28#include <linux/pm.h>
  29#include <linux/i2c/twl.h>
  30#include <linux/platform_device.h>
  31#include <linux/of.h>
  32
  33#include <asm/mach-types.h>
  34
  35static u8 twl4030_start_script_address = 0x2b;
  36
  37#define PWR_P1_SW_EVENTS        0x10
  38#define PWR_DEVOFF              (1 << 0)
  39#define SEQ_OFFSYNC             (1 << 0)
  40
  41#define PHY_TO_OFF_PM_MASTER(p)         (p - 0x36)
  42#define PHY_TO_OFF_PM_RECEIVER(p)       (p - 0x5b)
  43
  44/* resource - hfclk */
  45#define R_HFCLKOUT_DEV_GRP      PHY_TO_OFF_PM_RECEIVER(0xe6)
  46
  47/* PM events */
  48#define R_P1_SW_EVENTS          PHY_TO_OFF_PM_MASTER(0x46)
  49#define R_P2_SW_EVENTS          PHY_TO_OFF_PM_MASTER(0x47)
  50#define R_P3_SW_EVENTS          PHY_TO_OFF_PM_MASTER(0x48)
  51#define R_CFG_P1_TRANSITION     PHY_TO_OFF_PM_MASTER(0x36)
  52#define R_CFG_P2_TRANSITION     PHY_TO_OFF_PM_MASTER(0x37)
  53#define R_CFG_P3_TRANSITION     PHY_TO_OFF_PM_MASTER(0x38)
  54
  55#define LVL_WAKEUP      0x08
  56
  57#define ENABLE_WARMRESET (1<<4)
  58
  59#define END_OF_SCRIPT           0x3f
  60
  61#define R_SEQ_ADD_A2S           PHY_TO_OFF_PM_MASTER(0x55)
  62#define R_SEQ_ADD_S2A12         PHY_TO_OFF_PM_MASTER(0x56)
  63#define R_SEQ_ADD_S2A3          PHY_TO_OFF_PM_MASTER(0x57)
  64#define R_SEQ_ADD_WARM          PHY_TO_OFF_PM_MASTER(0x58)
  65#define R_MEMORY_ADDRESS        PHY_TO_OFF_PM_MASTER(0x59)
  66#define R_MEMORY_DATA           PHY_TO_OFF_PM_MASTER(0x5a)
  67
  68/* resource configuration registers
  69   <RESOURCE>_DEV_GRP   at address 'n+0'
  70   <RESOURCE>_TYPE      at address 'n+1'
  71   <RESOURCE>_REMAP     at address 'n+2'
  72   <RESOURCE>_DEDICATED at address 'n+3'
  73*/
  74#define DEV_GRP_OFFSET          0
  75#define TYPE_OFFSET             1
  76#define REMAP_OFFSET            2
  77#define DEDICATED_OFFSET        3
  78
  79/* Bit positions in the registers */
  80
  81/* <RESOURCE>_DEV_GRP */
  82#define DEV_GRP_SHIFT           5
  83#define DEV_GRP_MASK            (7 << DEV_GRP_SHIFT)
  84
  85/* <RESOURCE>_TYPE */
  86#define TYPE_SHIFT              0
  87#define TYPE_MASK               (7 << TYPE_SHIFT)
  88#define TYPE2_SHIFT             3
  89#define TYPE2_MASK              (3 << TYPE2_SHIFT)
  90
  91/* <RESOURCE>_REMAP */
  92#define SLEEP_STATE_SHIFT       0
  93#define SLEEP_STATE_MASK        (0xf << SLEEP_STATE_SHIFT)
  94#define OFF_STATE_SHIFT         4
  95#define OFF_STATE_MASK          (0xf << OFF_STATE_SHIFT)
  96
  97static u8 res_config_addrs[] = {
  98        [RES_VAUX1]     = 0x17,
  99        [RES_VAUX2]     = 0x1b,
 100        [RES_VAUX3]     = 0x1f,
 101        [RES_VAUX4]     = 0x23,
 102        [RES_VMMC1]     = 0x27,
 103        [RES_VMMC2]     = 0x2b,
 104        [RES_VPLL1]     = 0x2f,
 105        [RES_VPLL2]     = 0x33,
 106        [RES_VSIM]      = 0x37,
 107        [RES_VDAC]      = 0x3b,
 108        [RES_VINTANA1]  = 0x3f,
 109        [RES_VINTANA2]  = 0x43,
 110        [RES_VINTDIG]   = 0x47,
 111        [RES_VIO]       = 0x4b,
 112        [RES_VDD1]      = 0x55,
 113        [RES_VDD2]      = 0x63,
 114        [RES_VUSB_1V5]  = 0x71,
 115        [RES_VUSB_1V8]  = 0x74,
 116        [RES_VUSB_3V1]  = 0x77,
 117        [RES_VUSBCP]    = 0x7a,
 118        [RES_REGEN]     = 0x7f,
 119        [RES_NRES_PWRON] = 0x82,
 120        [RES_CLKEN]     = 0x85,
 121        [RES_SYSEN]     = 0x88,
 122        [RES_HFCLKOUT]  = 0x8b,
 123        [RES_32KCLKOUT] = 0x8e,
 124        [RES_RESET]     = 0x91,
 125        [RES_MAIN_REF]  = 0x94,
 126};
 127
 128static int twl4030_write_script_byte(u8 address, u8 byte)
 129{
 130        int err;
 131
 132        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_MEMORY_ADDRESS);
 133        if (err)
 134                goto out;
 135        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, byte, R_MEMORY_DATA);
 136out:
 137        return err;
 138}
 139
 140static int twl4030_write_script_ins(u8 address, u16 pmb_message,
 141                                           u8 delay, u8 next)
 142{
 143        int err;
 144
 145        address *= 4;
 146        err = twl4030_write_script_byte(address++, pmb_message >> 8);
 147        if (err)
 148                goto out;
 149        err = twl4030_write_script_byte(address++, pmb_message & 0xff);
 150        if (err)
 151                goto out;
 152        err = twl4030_write_script_byte(address++, delay);
 153        if (err)
 154                goto out;
 155        err = twl4030_write_script_byte(address++, next);
 156out:
 157        return err;
 158}
 159
 160static int twl4030_write_script(u8 address, struct twl4030_ins *script,
 161                                       int len)
 162{
 163        int err = -EINVAL;
 164
 165        for (; len; len--, address++, script++) {
 166                if (len == 1) {
 167                        err = twl4030_write_script_ins(address,
 168                                                script->pmb_message,
 169                                                script->delay,
 170                                                END_OF_SCRIPT);
 171                        if (err)
 172                                break;
 173                } else {
 174                        err = twl4030_write_script_ins(address,
 175                                                script->pmb_message,
 176                                                script->delay,
 177                                                address + 1);
 178                        if (err)
 179                                break;
 180                }
 181        }
 182        return err;
 183}
 184
 185static int twl4030_config_wakeup3_sequence(u8 address)
 186{
 187        int err;
 188        u8 data;
 189
 190        /* Set SLEEP to ACTIVE SEQ address for P3 */
 191        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A3);
 192        if (err)
 193                goto out;
 194
 195        /* P3 LVL_WAKEUP should be on LEVEL */
 196        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P3_SW_EVENTS);
 197        if (err)
 198                goto out;
 199        data |= LVL_WAKEUP;
 200        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P3_SW_EVENTS);
 201out:
 202        if (err)
 203                pr_err("TWL4030 wakeup sequence for P3 config error\n");
 204        return err;
 205}
 206
 207static int twl4030_config_wakeup12_sequence(u8 address)
 208{
 209        int err = 0;
 210        u8 data;
 211
 212        /* Set SLEEP to ACTIVE SEQ address for P1 and P2 */
 213        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_S2A12);
 214        if (err)
 215                goto out;
 216
 217        /* P1/P2 LVL_WAKEUP should be on LEVEL */
 218        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P1_SW_EVENTS);
 219        if (err)
 220                goto out;
 221
 222        data |= LVL_WAKEUP;
 223        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P1_SW_EVENTS);
 224        if (err)
 225                goto out;
 226
 227        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data, R_P2_SW_EVENTS);
 228        if (err)
 229                goto out;
 230
 231        data |= LVL_WAKEUP;
 232        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data, R_P2_SW_EVENTS);
 233        if (err)
 234                goto out;
 235
 236        if (machine_is_omap_3430sdp() || machine_is_omap_ldp()) {
 237                /* Disabling AC charger effect on sleep-active transitions */
 238                err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &data,
 239                                      R_CFG_P1_TRANSITION);
 240                if (err)
 241                        goto out;
 242                data &= ~(1<<1);
 243                err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, data,
 244                                       R_CFG_P1_TRANSITION);
 245                if (err)
 246                        goto out;
 247        }
 248
 249out:
 250        if (err)
 251                pr_err("TWL4030 wakeup sequence for P1 and P2" \
 252                        "config error\n");
 253        return err;
 254}
 255
 256static int twl4030_config_sleep_sequence(u8 address)
 257{
 258        int err;
 259
 260        /* Set ACTIVE to SLEEP SEQ address in T2 memory*/
 261        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_A2S);
 262
 263        if (err)
 264                pr_err("TWL4030 sleep sequence config error\n");
 265
 266        return err;
 267}
 268
 269static int twl4030_config_warmreset_sequence(u8 address)
 270{
 271        int err;
 272        u8 rd_data;
 273
 274        /* Set WARM RESET SEQ address for P1 */
 275        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, address, R_SEQ_ADD_WARM);
 276        if (err)
 277                goto out;
 278
 279        /* P1/P2/P3 enable WARMRESET */
 280        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P1_SW_EVENTS);
 281        if (err)
 282                goto out;
 283
 284        rd_data |= ENABLE_WARMRESET;
 285        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P1_SW_EVENTS);
 286        if (err)
 287                goto out;
 288
 289        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P2_SW_EVENTS);
 290        if (err)
 291                goto out;
 292
 293        rd_data |= ENABLE_WARMRESET;
 294        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P2_SW_EVENTS);
 295        if (err)
 296                goto out;
 297
 298        err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &rd_data, R_P3_SW_EVENTS);
 299        if (err)
 300                goto out;
 301
 302        rd_data |= ENABLE_WARMRESET;
 303        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, rd_data, R_P3_SW_EVENTS);
 304out:
 305        if (err)
 306                pr_err("TWL4030 warmreset seq config error\n");
 307        return err;
 308}
 309
 310static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
 311{
 312        int rconfig_addr;
 313        int err;
 314        u8 type;
 315        u8 grp;
 316        u8 remap;
 317
 318        if (rconfig->resource > TOTAL_RESOURCES) {
 319                pr_err("TWL4030 Resource %d does not exist\n",
 320                        rconfig->resource);
 321                return -EINVAL;
 322        }
 323
 324        rconfig_addr = res_config_addrs[rconfig->resource];
 325
 326        /* Set resource group */
 327        err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &grp,
 328                              rconfig_addr + DEV_GRP_OFFSET);
 329        if (err) {
 330                pr_err("TWL4030 Resource %d group could not be read\n",
 331                        rconfig->resource);
 332                return err;
 333        }
 334
 335        if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
 336                grp &= ~DEV_GRP_MASK;
 337                grp |= rconfig->devgroup << DEV_GRP_SHIFT;
 338                err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 339                                       grp, rconfig_addr + DEV_GRP_OFFSET);
 340                if (err < 0) {
 341                        pr_err("TWL4030 failed to program devgroup\n");
 342                        return err;
 343                }
 344        }
 345
 346        /* Set resource types */
 347        err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &type,
 348                                rconfig_addr + TYPE_OFFSET);
 349        if (err < 0) {
 350                pr_err("TWL4030 Resource %d type could not be read\n",
 351                        rconfig->resource);
 352                return err;
 353        }
 354
 355        if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
 356                type &= ~TYPE_MASK;
 357                type |= rconfig->type << TYPE_SHIFT;
 358        }
 359
 360        if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
 361                type &= ~TYPE2_MASK;
 362                type |= rconfig->type2 << TYPE2_SHIFT;
 363        }
 364
 365        err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 366                                type, rconfig_addr + TYPE_OFFSET);
 367        if (err < 0) {
 368                pr_err("TWL4030 failed to program resource type\n");
 369                return err;
 370        }
 371
 372        /* Set remap states */
 373        err = twl_i2c_read_u8(TWL_MODULE_PM_RECEIVER, &remap,
 374                              rconfig_addr + REMAP_OFFSET);
 375        if (err < 0) {
 376                pr_err("TWL4030 Resource %d remap could not be read\n",
 377                        rconfig->resource);
 378                return err;
 379        }
 380
 381        if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
 382                remap &= ~OFF_STATE_MASK;
 383                remap |= rconfig->remap_off << OFF_STATE_SHIFT;
 384        }
 385
 386        if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
 387                remap &= ~SLEEP_STATE_MASK;
 388                remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
 389        }
 390
 391        err = twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER,
 392                               remap,
 393                               rconfig_addr + REMAP_OFFSET);
 394        if (err < 0) {
 395                pr_err("TWL4030 failed to program remap\n");
 396                return err;
 397        }
 398
 399        return 0;
 400}
 401
 402static int load_twl4030_script(struct twl4030_script *tscript,
 403               u8 address)
 404{
 405        int err;
 406        static int order;
 407
 408        /* Make sure the script isn't going beyond last valid address (0x3f) */
 409        if ((address + tscript->size) > END_OF_SCRIPT) {
 410                pr_err("TWL4030 scripts too big error\n");
 411                return -EINVAL;
 412        }
 413
 414        err = twl4030_write_script(address, tscript->script, tscript->size);
 415        if (err)
 416                goto out;
 417
 418        if (tscript->flags & TWL4030_WRST_SCRIPT) {
 419                err = twl4030_config_warmreset_sequence(address);
 420                if (err)
 421                        goto out;
 422        }
 423        if (tscript->flags & TWL4030_WAKEUP12_SCRIPT) {
 424                err = twl4030_config_wakeup12_sequence(address);
 425                if (err)
 426                        goto out;
 427                order = 1;
 428        }
 429        if (tscript->flags & TWL4030_WAKEUP3_SCRIPT) {
 430                err = twl4030_config_wakeup3_sequence(address);
 431                if (err)
 432                        goto out;
 433        }
 434        if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
 435                if (!order)
 436                        pr_warning("TWL4030: Bad order of scripts (sleep "\
 437                                        "script before wakeup) Leads to boot"\
 438                                        "failure on some boards\n");
 439                err = twl4030_config_sleep_sequence(address);
 440        }
 441out:
 442        return err;
 443}
 444
 445int twl4030_remove_script(u8 flags)
 446{
 447        int err = 0;
 448
 449        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
 450                               TWL4030_PM_MASTER_PROTECT_KEY);
 451        if (err) {
 452                pr_err("twl4030: unable to unlock PROTECT_KEY\n");
 453                return err;
 454        }
 455
 456        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG2,
 457                               TWL4030_PM_MASTER_PROTECT_KEY);
 458        if (err) {
 459                pr_err("twl4030: unable to unlock PROTECT_KEY\n");
 460                return err;
 461        }
 462
 463        if (flags & TWL4030_WRST_SCRIPT) {
 464                err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
 465                                       R_SEQ_ADD_WARM);
 466                if (err)
 467                        return err;
 468        }
 469        if (flags & TWL4030_WAKEUP12_SCRIPT) {
 470                err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
 471                                       R_SEQ_ADD_S2A12);
 472                if (err)
 473                        return err;
 474        }
 475        if (flags & TWL4030_WAKEUP3_SCRIPT) {
 476                err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
 477                                       R_SEQ_ADD_S2A3);
 478                if (err)
 479                        return err;
 480        }
 481        if (flags & TWL4030_SLEEP_SCRIPT) {
 482                err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, END_OF_SCRIPT,
 483                                       R_SEQ_ADD_A2S);
 484                if (err)
 485                        return err;
 486        }
 487
 488        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
 489                               TWL4030_PM_MASTER_PROTECT_KEY);
 490        if (err)
 491                pr_err("TWL4030 Unable to relock registers\n");
 492
 493        return err;
 494}
 495
 496int twl4030_power_configure_scripts(struct twl4030_power_data *pdata)
 497{
 498        int err;
 499        int i;
 500        u8 address = twl4030_start_script_address;
 501
 502        for (i = 0; i < pdata->num; i++) {
 503                err = load_twl4030_script(pdata->scripts[i], address);
 504                if (err)
 505                        return err;
 506                address += pdata->scripts[i]->size;
 507        }
 508
 509        return 0;
 510}
 511
 512int twl4030_power_configure_resources(struct twl4030_power_data *pdata)
 513{
 514        struct twl4030_resconfig *resconfig = pdata->resource_config;
 515        int err;
 516
 517        if (resconfig) {
 518                while (resconfig->resource) {
 519                        err = twl4030_configure_resource(resconfig);
 520                        if (err)
 521                                return err;
 522                        resconfig++;
 523                }
 524        }
 525
 526        return 0;
 527}
 528
 529/*
 530 * In master mode, start the power off sequence.
 531 * After a successful execution, TWL shuts down the power to the SoC
 532 * and all peripherals connected to it.
 533 */
 534void twl4030_power_off(void)
 535{
 536        int err;
 537
 538        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, PWR_DEVOFF,
 539                               TWL4030_PM_MASTER_P1_SW_EVENTS);
 540        if (err)
 541                pr_err("TWL4030 Unable to power off\n");
 542}
 543
 544static bool twl4030_power_use_poweroff(struct twl4030_power_data *pdata,
 545                                        struct device_node *node)
 546{
 547        if (pdata && pdata->use_poweroff)
 548                return true;
 549
 550        if (of_property_read_bool(node, "ti,use_poweroff"))
 551                return true;
 552
 553        return false;
 554}
 555
 556int twl4030_power_probe(struct platform_device *pdev)
 557{
 558        struct twl4030_power_data *pdata = pdev->dev.platform_data;
 559        struct device_node *node = pdev->dev.of_node;
 560        int err = 0;
 561        int err2 = 0;
 562        u8 val;
 563
 564        if (!pdata && !node) {
 565                dev_err(&pdev->dev, "Platform data is missing\n");
 566                return -EINVAL;
 567        }
 568
 569        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, TWL4030_PM_MASTER_KEY_CFG1,
 570                               TWL4030_PM_MASTER_PROTECT_KEY);
 571        err |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER,
 572                               TWL4030_PM_MASTER_KEY_CFG2,
 573                               TWL4030_PM_MASTER_PROTECT_KEY);
 574
 575        if (err) {
 576                pr_err("TWL4030 Unable to unlock registers\n");
 577                return err;
 578        }
 579
 580        if (pdata) {
 581                /* TODO: convert to device tree */
 582                err = twl4030_power_configure_scripts(pdata);
 583                if (err) {
 584                        pr_err("TWL4030 failed to load scripts\n");
 585                        goto relock;
 586                }
 587                err = twl4030_power_configure_resources(pdata);
 588                if (err) {
 589                        pr_err("TWL4030 failed to configure resource\n");
 590                        goto relock;
 591                }
 592        }
 593
 594        /* Board has to be wired properly to use this feature */
 595        if (twl4030_power_use_poweroff(pdata, node) && !pm_power_off) {
 596                /* Default for SEQ_OFFSYNC is set, lets ensure this */
 597                err = twl_i2c_read_u8(TWL_MODULE_PM_MASTER, &val,
 598                                      TWL4030_PM_MASTER_CFG_P123_TRANSITION);
 599                if (err) {
 600                        pr_warning("TWL4030 Unable to read registers\n");
 601
 602                } else if (!(val & SEQ_OFFSYNC)) {
 603                        val |= SEQ_OFFSYNC;
 604                        err = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, val,
 605                                        TWL4030_PM_MASTER_CFG_P123_TRANSITION);
 606                        if (err) {
 607                                pr_err("TWL4030 Unable to setup SEQ_OFFSYNC\n");
 608                                goto relock;
 609                        }
 610                }
 611
 612                pm_power_off = twl4030_power_off;
 613        }
 614
 615relock:
 616        err2 = twl_i2c_write_u8(TWL_MODULE_PM_MASTER, 0,
 617                               TWL4030_PM_MASTER_PROTECT_KEY);
 618        if (err2) {
 619                pr_err("TWL4030 Unable to relock registers\n");
 620                return err2;
 621        }
 622
 623        return err;
 624}
 625
 626static int twl4030_power_remove(struct platform_device *pdev)
 627{
 628        return 0;
 629}
 630
 631#ifdef CONFIG_OF
 632static const struct of_device_id twl4030_power_of_match[] = {
 633        {.compatible = "ti,twl4030-power", },
 634        { },
 635};
 636MODULE_DEVICE_TABLE(of, twl4030_power_of_match);
 637#endif
 638
 639static struct platform_driver twl4030_power_driver = {
 640        .driver = {
 641                .name   = "twl4030_power",
 642                .owner  = THIS_MODULE,
 643                .of_match_table = of_match_ptr(twl4030_power_of_match),
 644        },
 645        .probe          = twl4030_power_probe,
 646        .remove         = twl4030_power_remove,
 647};
 648
 649module_platform_driver(twl4030_power_driver);
 650
 651MODULE_AUTHOR("Nokia Corporation");
 652MODULE_AUTHOR("Texas Instruments, Inc.");
 653MODULE_DESCRIPTION("Power management for TWL4030");
 654MODULE_LICENSE("GPL");
 655MODULE_ALIAS("platform:twl4030_power");
 656
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.