This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

AM5708: eQEP driver load

Other Parts Discussed in Thread: AM5708

Hi:

board:  custom AM5708  

SDK: ti-processor-sdk-linux-rt-am57xx-evm-05.03.00.07-Linux-x86-Install.bin

Refer to the following url to download the eQEP driver file:

https://e2echina.ti.com/question_answer/dsp_arm/sitara_arm/f/25/t/78229?keyMatch=eQEP&tisearch=Search-CN-Everything

1、certify pin multiple

2、arch/arm/boot/dts/dra7.dtsi   add  eqep0  node

Add the following to our own device tree

3、Add the tieqep.c file in /driver/misc and compile the build module

pwm-tipwmss.h                      

/*
 * TI eQEP driver for AM57xx devices
 *
 * Copyright (C) 2013 Nathaniel R. Lewis - http://nathanielrlewis.com/
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *
 * sysfs entries
 *   - position = absolute - current position; relative - last latched value
 *   - mode => 0 - absolute; 1 - relative
 *   - period => sampling period for the hardware
 *   - enable => 0 - eQEP disabled, 1 - eQEP enabled
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/of_device.h>
#include <linux/pinctrl/consumer.h>
#include <linux/input.h>

// Include the PWMSS subsystem headers, because this unit controls
// whether our clock source is enabled, and if eQEP is to be
// enabled, we need to start the clock
#include "../pwm/pwm-tipwmss.h"

// eQEP register offsets from its base IO address
#define QPOSCNT    0x0000
#define QPOSINIT   0x0004
#define QPOSMAX    0x0008
#define QPOSCMP    0x000C
#define QPOSILAT   0x0010
#define QPOSSLAT   0x0014
#define QPOSLAT    0x0018
#define QUTMR      0x001C
#define QUPRD      0x0020    
#define QWDTMR     0x0024
#define QWDPRD     0x0026
#define QDECCTL    0x0028
#define QEPCTL     0x002A
#define QCAPCTL    0x002C
#define QPOSCTL    0x002E
#define QEINT      0x0030
#define QFLG       0x0032
#define QCLR       0x0034
#define QFRC       0x0036
#define QEPSTS     0x0038
#define QCTMR      0x003A
#define QCPRD      0x003C
#define QCTMRLAT   0x003E
#define QCPRDLAT   0x0040
#define QREVID     0x005C

// Bits for the QDECTL register
#define QSRC1      (0x0001 << 15)
#define QSRC0      (0x0001 << 14)
#define SOEN       (0x0001 << 13)
#define SPSEL      (0x0001 << 12)
#define XCR        (0x0001 << 11)
#define SWAP       (0x0001 << 10)
#define IGATE      (0x0001 << 9)
#define QAP        (0x0001 << 8)
#define QBP        (0x0001 << 7)
#define QIP        (0x0001 << 6)
#define QSP        (0x0001 << 5)

// Bits for the QEPCTL register
#define FREESOFT1  (0x0001 << 15)
#define FREESOFT0  (0x0001 << 14)
#define PCRM1      (0x0001 << 13)
#define PCRM0      (0x0001 << 12)
#define SEI1       (0x0001 << 11)
#define SEI0       (0x0001 << 10)
#define IEI1       (0x0001 << 9)
#define IEI0       (0x0001 << 8)
#define SWI        (0x0001 << 7)
#define SEL        (0x0001 << 6)
#define IEL1       (0x0001 << 5)
#define IEL0       (0x0001 << 4)
#define PHEN       (0x0001 << 3)
#define QCLM       (0x0001 << 2)
#define UTE        (0x0001 << 1)
#define WDE        (0x0001 << 0)

// Bits for the QCAPCTL register
#define CEN        (0x0001 << 15)
#define CCPS2      (0x0001 << 6)
#define CCPS0      (0x0001 << 5)
#define CCPS1      (0x0001 << 4)
#define UPPS3      (0x0001 << 3)
#define UPPS2      (0x0001 << 2)
#define UPPS1      (0x0001 << 1)
#define UPPS0      (0x0001 << 0)

// Bits for the QPOSCTL register
#define PCSHDW     (0x0001 << 15)
#define PCLOAD     (0x0001 << 14)
#define PCPOL      (0x0001 << 13)
#define PCE        (0x0001 << 12)
#define PCSPW11    (0x0001 << 11)
#define PCSPW10    (0x0001 << 10)
#define PCSPW9    (0x0001 << 9)
#define PCSPW8    (0x0001 << 8)
#define PCSPW7    (0x0001 << 7)
#define PCSPW6    (0x0001 << 6)
#define PCSPW5    (0x0001 << 5)
#define PCSPW4    (0x0001 << 4)
#define PCSPW3    (0x0001 << 3)
#define PCSPW2    (0x0001 << 2)
#define PCSPW1    (0x0001 << 1)
#define PCSPW0    (0x0001 << 0)

// Bits for the interrupt registers
#define EQEP_INTERRUPT_MASK (0x0FFF)
#define UTOF                (0x0001 << 11)

// Bits to control the clock in the PWMSS subsystem
#define PWMSS_EQEPCLK_EN        BIT(4)
#define PWMSS_EQEPCLK_STOP_REQ  BIT(5)
#define PWMSS_EQEPCLK_EN_ACK    BIT(4)

// Modes for the eQEP unit
//  Absolute - the position entry represents the current position of the encoder.
//             Poll this value and it will be notified every period nanoseconds
//  Relative - the position entry represents the last latched position of the encoder
//             This value is latched every period nanoseconds and the internal counter
//             is subsequenty reset
#define TIEQEP_MODE_ABSOLUTE    0
#define TIEQEP_MODE_RELATIVE    1

// Structure defining the characteristics of the eQEP unit
struct eqep_chip
{
    // Platform device for this eQEP unit
    struct platform_device *pdev;
    
    // Pointer to the base of the memory of the eQEP unit
    void __iomem           *mmio_base;
    
    // SYSCLKOUT to the eQEP unit
    u32                     clk_rate;
    
    // IRQ for the eQEP unit
    u16                     irq;
    
    // Mode of the eQEP unit
    u8                      mode;
    
    // work stuct for the notify userspace work
    struct work_struct      notify_work;
    
    // Backup for driver suspension
    u16                     prior_qepctl;
    u16                     prior_qeint;
};

// Notify userspace work
void notify_handler (struct work_struct *work)
{
    // Get a reference to the eQEP driver
    struct eqep_chip *eqep = container_of(work, struct eqep_chip, notify_work);
    
    // Notify the userspace
    sysfs_notify(&eqep->pdev->dev.kobj, NULL, "position");
}

// eQEP Interrupt handler
static irqreturn_t eqep_irq_handler(int irq, void *dev_id)
{
    // Get the instance information
    struct platform_device *pdev = dev_id;
    struct eqep_chip       *eqep = platform_get_drvdata(pdev);

    // Get the interrupt flags
    u16 iflags = readw(eqep->mmio_base + QFLG) & EQEP_INTERRUPT_MASK;

    // Check the interrupt source(s)
    if(iflags & UTOF)
    {
        // Handle the unit timer overflow interrupt by notifying any potential pollers
        schedule_work(&eqep->notify_work);
    }
    
    // Clear interrupt flags (write back triggered flags to the clear register)
    writew(iflags, eqep->mmio_base + QCLR);
    
    // Return that the IRQ was handled successfully
    return IRQ_HANDLED;
}

// Function to read whether the eQEP unit is enabled or disabled
static ssize_t eqep_get_enabled(struct device *dev, struct device_attribute *attr, char *buf)
{
    // Get the instance structure
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    
    // Read the qep control register and mask all but the enabled bit
    u16 enabled = readw(eqep->mmio_base + QEPCTL) & PHEN;
    
    // Return the target in string format
    return sprintf(buf, "%u\n", (enabled) ? 1 : 0);
}

// Function to set if the eQEP is enabled
static ssize_t eqep_set_enabled(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // Get the instance structure
    int rc;
    u16 val;
    u8  enabled;
    struct eqep_chip *eqep = dev_get_drvdata(dev);

     // Convert the input string to an 8 bit uint
    if ((rc = kstrtou8(buf, 0, &enabled)))
        return rc;
        
    // Get the existing state of QEPCTL
    val = readw(eqep->mmio_base + QEPCTL);
    
    // If we passed a number that is not 0, enable the eQEP
    if(enabled)
    {
        // Enable the eQEP (Set PHEN in QEPCTL)
        val = val | PHEN;
    } else
    {
        // Disable the eQEP (Clear PHEN in QEPCTL)
        val = val & ~PHEN;
    }
    
    // Write flags back to control register
    writew(val, eqep->mmio_base + QEPCTL);
    
    // Return buffer length consumed (all)
    return count;
}

// Function to read the current position of the eQEP
static ssize_t eqep_get_position(struct device *dev, struct device_attribute *attr, char *buf)
{
    // Get the instance structure
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    
    // A variable to return the position with
    s32 position = 0;
    
    // Check the mode
    if(eqep->mode == TIEQEP_MODE_ABSOLUTE)
    {
        // If we are in absolute mode, we need the current value of the eQEP hardware
        position = readl(eqep->mmio_base + QPOSCNT);
    } else if(eqep->mode == TIEQEP_MODE_RELATIVE)
    {
        // If we are in relative mode, we need the last latched value of the eQEP hardware
        position = readl(eqep->mmio_base + QPOSLAT);
    }
    
    // Return the target in string format
    return sprintf(buf, "%d\n", position);
}

// Function to set the position of the eQEP hardware
static ssize_t eqep_set_position(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // Get the instance structure
    int rc;
    s32 position;
    struct eqep_chip *eqep = dev_get_drvdata(dev);

     // Convert the input string to an 8 bit uint
    if ((rc = kstrtos32(buf, 0, &position)))
        return rc;
        
    // If we are in absolute mode, set the position of the encoder, discard relative mode because thats pointless
    if(eqep->mode == TIEQEP_MODE_ABSOLUTE)
    {
        // If we are in absolute mode, we need the current value of the eQEP hardware
        writel(position, eqep->mmio_base + QPOSCNT);
    }
    
    // Return buffer length consumed (all)
    return count;
}

// Function to read the period of the unit time event timer
static ssize_t eqep_get_timer_period(struct device *dev, struct device_attribute *attr, char *buf)
{
    // Get the instance structure
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    u64               period = 0;
        
    // Check if the period timer is enabled, if not, return 0
    if(!(readw(eqep->mmio_base + QEPCTL) & UTE))
    {
        return sprintf(buf, "0\n");
    }
    
    // Convert from counts per interrupt back into period_ns
    period = readl(eqep->mmio_base + QUPRD);
    period = period * NSEC_PER_SEC;
    do_div(period, eqep->clk_rate);
    
    // Otherwise write out the data
    return sprintf(buf, "%llu\n", period);
}

// Function to set the unit timer period.  0 = off, greater than zero sets the period
static ssize_t eqep_set_timer_period(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    int rc;
    u16 tmp;
    u64 period;
    
    // Get the instance structure
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    
    // Convert the passed string to a 64 bit uint
    if((rc = kstrtou64(buf, 0, &period)))
        return rc;
        
    // Disable the unit timer before modifying its period register
    tmp = readw(eqep->mmio_base + QEPCTL);
    tmp = tmp & ~UTE & ~QCLM;
    writew(tmp, eqep->mmio_base + QEPCTL);
    
    // Zero the unit timer counter register
    writel(0x0, eqep->mmio_base + QUTMR);
        
    // If we want the timer enabled (a period that is non zero has been passed)
    if(period)
    {
        // Otherwise calculate the period
        period = period * eqep->clk_rate;
        do_div(period, NSEC_PER_SEC);
        
        // Set this period into the unit timer period register
        writel(period & 0x00000000FFFFFFFF, eqep->mmio_base + QUPRD);
        
        // Enable the unit timer, and latch QPOSLAT to QPOSCNT on overflow
        tmp = readw(eqep->mmio_base + QEPCTL);
        tmp = tmp | UTE | QCLM;
        writew(tmp, eqep->mmio_base + QEPCTL);
    }
    
    // Return consumed buffer count
    return count;
}

// Function to read the mode of the eQEP hardware
static ssize_t eqep_get_mode(struct device *dev, struct device_attribute *attr, char *buf)
{
    // Get the instance structure
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    
    // Return the mode
    return sprintf(buf, "%u\n", eqep->mode);
}

// Function to set the mode of the eQEP hardware
static ssize_t eqep_set_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
{
    // Get the instance structure
    int rc;
    u16 val;
    u8  tmp_mode;
    struct eqep_chip *eqep = dev_get_drvdata(dev);

     // Convert the input string to an 8 bit uint
    if ((rc = kstrtou8(buf, 0, &tmp_mode)))
        return rc;
        
    // Get the existing state of QEPCTL
    val = readw(eqep->mmio_base + QEPCTL);
    
    // Check the mode that was passed
    if(tmp_mode == TIEQEP_MODE_ABSOLUTE)
    {
        // In absolute mode, we don't want to reset the intenal hardware based on time,
        // so disable the unit timer position reset (Set PCRM[1:0] = 0)
        val = val & ~PCRM1 & ~PCRM0;
        
        // Store the mode as absolute
        eqep->mode = TIEQEP_MODE_ABSOLUTE;
    } else if(tmp_mode == TIEQEP_MODE_RELATIVE)
    {
        // In relative mode, we want to latch the value of the eQEP hardware on the 
        // overflow of the unit timer.  So enable the unit timer position reset
        // (Set PCRM[1:0] = 3)
        val = val | PCRM1 | PCRM0;
        
        // Store the mode as relative
        eqep->mode = TIEQEP_MODE_RELATIVE;
    }
    
    // Write the new value back to the control register    
    writew(val, eqep->mmio_base + QEPCTL);
    
    // Return buffer length consumed (all)
    return count;
}

// Bind read/write functions to sysfs entries
static DEVICE_ATTR(enabled,  0644, eqep_get_enabled,      eqep_set_enabled);
static DEVICE_ATTR(position, 0644, eqep_get_position,     eqep_set_position);
static DEVICE_ATTR(period,   0644, eqep_get_timer_period, eqep_set_timer_period);
static DEVICE_ATTR(mode,     0644, eqep_get_mode,         eqep_set_mode);

// Array holding all of the sysfs entries
static const struct attribute *eqep_attrs[] = {
    &dev_attr_enabled.attr,
    &dev_attr_position.attr,
    &dev_attr_period.attr,
    &dev_attr_mode.attr,
    NULL,
};

// Driver function group
static const struct attribute_group eqep_device_attr_group = {
    .attrs = (struct attribute **) eqep_attrs,
};

// Driver compatibility list
static struct of_device_id eqep_of_match[] = 
{
    { .compatible = "ti,am57xx-eqep" },
    { }
};

// Register our compatibilities for device trees
MODULE_DEVICE_TABLE(of, eqep_of_match);

#define PWMSS_CLKCONFIG		0x8	/* Clock gating reg */
#define PWMSS_CLKSTATUS		0xc	/* Clock gating status reg */

struct pwmss_info {
	void __iomem	*mmio_base;
	struct mutex	pwmss_lock;
	u16		pwmss_clkconfig;
};

u16 pwmss_submodule_state_change(struct device *dev, int set)
{
	struct pwmss_info *info = dev_get_drvdata(dev);
	u16 val;

	mutex_lock(&info->pwmss_lock);
	val = readw(info->mmio_base + PWMSS_CLKCONFIG);
	val |= set;
	writew(val , info->mmio_base + PWMSS_CLKCONFIG);
	mutex_unlock(&info->pwmss_lock);

	return readw(info->mmio_base + PWMSS_CLKSTATUS);
}

// Create an instance of the eQEP driver
static int eqep_probe(struct platform_device *pdev)
{
    struct resource  *r;
    struct clk       *clk;
    struct eqep_chip *eqep;
    struct pinctrl   *pinctrl;
    int               ret;
    u64               period;
    u16               status;
    u32               value;

    // Select any default pins possible provided through the device tree
    pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
    if (IS_ERR(pinctrl))
    {
        dev_warn(&pdev->dev, "unable to select pin group\n");
    }
    
    // Allocate a eqep_driver object
    eqep = devm_kzalloc(&pdev->dev, sizeof(struct eqep_chip), GFP_KERNEL);
    if (!eqep) {
        dev_err(&pdev->dev, "failed to allocate memory\n");
        return -ENOMEM;
    }

    // Get a handle to the system clock object
    clk = devm_clk_get(&pdev->dev, "fck");
    if (IS_ERR(clk)) {
        dev_err(&pdev->dev, "failed to get clock\n");
        return PTR_ERR(clk);
    }

    // Get the frequency of the system clock
    eqep->clk_rate = clk_get_rate(clk);
    if (!eqep->clk_rate) {
        dev_err(&pdev->dev, "failed to get clock rate\n");
        return -EINVAL;
    }
    
    // Get a resource containing the IRQ for this eQEP controller
    r = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    if (unlikely(!r)) {
        dev_err(&pdev->dev, "Invalid IRQ resource\n");
        return -ENODEV;
    }
    
    // Store the irq
    eqep->irq = r->start;

    // Get a resource containing the requested (from DT) memory address and range of eQEP controller
    r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    if (!r) {
        dev_err(&pdev->dev, "no memory resource defined\n");
        return -ENODEV;
    }

    // Remap the eQEP controller memory into our own memory space
    eqep->mmio_base = devm_ioremap_resource(&pdev->dev, r);
    if (!eqep->mmio_base)
        return  -EADDRNOTAVAIL;
    
    // Store the platform device in our eQEP data structure for later usage
    eqep->pdev = pdev;
    
    // Subscribe to the eQEP interrupt
    if (request_irq(eqep->irq, eqep_irq_handler, IRQF_IRQPOLL, "eqep_interrupt", pdev))
    {
        dev_err(&pdev->dev, "unable to request irq for eQEP\n");
        return -ENODEV;
    }

    // Register controls to sysfs
    if (sysfs_create_group(&pdev->dev.kobj, &eqep_device_attr_group)) 
    {
        dev_err(&pdev->dev, "sysfs creation failed\n");
        return -EINVAL;
    }
    
    // Read decoder control settings
    status = readw(eqep->mmio_base + QDECCTL);
    
    // Quadrature mode or direction mode
    if(of_property_read_u32(pdev->dev.of_node, "count_mode", &value))
        status = status & ~QSRC1 & ~QSRC0;
    else
        status = ((value) ? status | QSRC0 : status & ~QSRC0) & ~QSRC1;
    
    // Should we invert the qa input
    if(of_property_read_u32(pdev->dev.of_node, "invert_qa", &value))
        status = status & ~QAP;
    else
        status = (value) ? status | QAP : status & ~QAP;
    
    // Should we invert the qb input
    if(of_property_read_u32(pdev->dev.of_node, "invert_qb", &value))
        status = status & ~QBP;
    else
        status = (value) ? status | QBP : status & ~QBP;
    
    // Should we invert the index input
    if(of_property_read_u32(pdev->dev.of_node, "invert_qi", &value))
        status = status & ~QIP;
    else
        status = (value) ? status | QIP : status & ~QIP;
    
    // Should we invert the strobe input
    if(of_property_read_u32(pdev->dev.of_node, "invert_qs", &value))
        status = status & ~QSP;
    else
        status = (value) ? status | QSP : status & ~QSP;
    
    // Should we swap the cha and chb inputs
    if(of_property_read_u32(pdev->dev.of_node, "swap_inputs", &value))
        status = status & ~SWAP;
    else
        status = (value) ? status | SWAP : status & ~SWAP;
        
    // Write the decoder control settings back to the control register
    writew(status, eqep->mmio_base + QDECCTL);
    
    // Initialize the position counter to zero
    writel(0, eqep->mmio_base + QPOSINIT);
    
    // This is pretty ingenious if I do say so myself.  The eQEP subsystem has a register
    // that defined the maximum value of the encoder as an unsigned.  If the counter is zero
    // and decrements again, it is set to QPOSMAX.  If you cast -1 (signed int) to
    // to an unsigned, you will notice that -1 == UINT_MAX.  So when the counter is set to this
    // maximum position, when read into a signed int, it will equal -1.  Two's complement for 
    // the WIN!!
    writel(-1, eqep->mmio_base + QPOSMAX);
    
    // Enable some interrupts
    status = readw(eqep->mmio_base + QEINT);
    status = status | UTOF;
            // UTOF - Unit Time Period interrupt.  This is triggered when the unit timer period expires
            // 
    writew(status, eqep->mmio_base + QEINT);
    
    // Calculate the timer ticks per second
    period = 1000000000;
    period = period * eqep->clk_rate;
    do_div(period, NSEC_PER_SEC);
    
    // Set this period into the unit timer period register
    writel(period & 0x00000000FFFFFFFF, eqep->mmio_base + QUPRD);
    
    // Enable the eQEP with basic position counting turned on
    status = readw(eqep->mmio_base + QEPCTL);
    status = status | PHEN | IEL0 | SWI | UTE | QCLM;
            // PHEN - Quadrature position counter enable bit
            // IEL0 - Latch QPOSILAT on index signal.  This can be rising or falling, IEL[1:0] = 0 is reserved
            // SWI  - Software initialization of position count register.  Basic set QPOSCNT <= QPOSINIT
            // UTE  - unit timer enable
            // QCLM - latch QPOSLAT to QPOSCNT upon unit timer overflow
    writew(status, eqep->mmio_base + QEPCTL);
    
    // We default to absolute mode
    eqep->mode = TIEQEP_MODE_ABSOLUTE;

    // Enable the power management runtime
    pm_runtime_enable(&pdev->dev);
    
    // Increment the device usage count and run pm_runtime_resume()
    pm_runtime_get_sync(&pdev->dev);

    // Enable the clock to the eQEP unit
    status = pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EQEPCLK_EN);
    
    // If we failed to enable the clocks, fail out
    if (!(status & PWMSS_EQEPCLK_EN_ACK)) 
    {
        dev_err(&pdev->dev, "PWMSS config space clock enable failed\n");
        ret = -EINVAL;
        goto pwmss_clk_failure;
    }
    
    // Initialize the notify work struture
    INIT_WORK(&eqep->notify_work, notify_handler);

    // Decrement the device usage count (twice) and run pm_runtime_idle() if zero
    pm_runtime_put_sync(&pdev->dev);

    // Set the platform driver data to the data object we've been creating for the eQEP unit
    platform_set_drvdata(pdev, eqep);
    
    // Success!
    //printk(KERN_INFO "EQEP irq = %d, system clock = %u\n", eqep->irq, eqep->clk_rate);
    return 0;

    // If a failure occurred, stop the runtime power management
pwmss_clk_failure:
    pm_runtime_put_sync(&pdev->dev);
    pm_runtime_disable(&pdev->dev);
    return ret;
}

// Remove an instance of the eQEP driver
static int eqep_remove(struct platform_device *pdev)
{
    // Get the eQEP driver data from the platform device structure
    struct eqep_chip *eqep = platform_get_drvdata(pdev);
    
    // Cancel work
    cancel_work_sync(&eqep->notify_work);
    
    // Unmap from sysfs
    sysfs_remove_group(&pdev->dev.kobj, &eqep_device_attr_group);
    
    // Release important assets
    free_irq(eqep->irq, pdev);

    // Increment the device usage count and run pm_runtime_resume()
    pm_runtime_get_sync(&pdev->dev);
    
    // Disable the eQEP clock
    pwmss_submodule_state_change(pdev->dev.parent, PWMSS_EQEPCLK_STOP_REQ);
    
    // Decrement the device usage count (twice) and run pm_runtime_idle() if zero
    pm_runtime_put_sync(&pdev->dev);
    pm_runtime_put_sync(&pdev->dev);
    
    // Disable the runtime power management of this device 
    pm_runtime_disable(&pdev->dev);
    
    // Return success
    return 0;
}

// Power management suspend device
static int eqep_suspend(struct device *dev)
{
    // Get the eqep driver information
    struct eqep_chip   *eqep = dev_get_drvdata(dev);
    u16                 tmp;
    
    // Shut down interrupts
    eqep->prior_qeint = readw(eqep->mmio_base + QEINT);
    tmp = eqep->prior_qeint & ~UTOF;
            // UTOF - Unit Time Period interrupt. 
    writew(tmp, eqep->mmio_base + QEINT);
        
    // Get the existing state of QEPCTL
    eqep->prior_qepctl = readw(eqep->mmio_base + QEPCTL);
    
    // Disable eQEP controller
    writew(eqep->prior_qepctl & ~PHEN, eqep->mmio_base + QEPCTL);
    
    // Decrement the device usage count and run pm_runtime_idle() if zero
    pm_runtime_put_sync(dev);
    
    // Return success
    return 0;
}

// Power management wake device back up
static int eqep_resume(struct device *dev)
{
    // Get the eqep driver information
    struct eqep_chip *eqep = dev_get_drvdata(dev);
    
    // Restore interrupt enabled register
    writew(eqep->prior_qeint, eqep->mmio_base + QEINT);
    
    // Restore prior qep control register
    writew(eqep->prior_qepctl, eqep->mmio_base + QEPCTL);

    // Increment the device usage count and run pm_runtime_resume()
    pm_runtime_get_sync(dev);
    
    // Success
    return 0;
}

// create pm functions object
static SIMPLE_DEV_PM_OPS(eqep_pm_ops, eqep_suspend, eqep_resume);

// Platform driver information
static struct platform_driver eqep_driver = {
    .driver = {
        .name           = "eqep",
        .owner          = THIS_MODULE,
        .pm             = &eqep_pm_ops,
        .of_match_table = eqep_of_match,
    },
    .probe = eqep_probe,
    .remove = eqep_remove,
};

// Register this platform driver
module_platform_driver(eqep_driver);

// Module information
MODULE_DESCRIPTION("TI eQEP driver");
MODULE_AUTHOR("Nathaniel R. Lewis");
MODULE_LICENSE("GPL");




4、Insert the module

insmode tieqep.ko

No print messages were found, and no device files were found.What will happen if the load is successful? Where will the device be generated?